Files
SkyArtShop/website/public/shop.html

885 lines
26 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Shop all products - Sky Art Shop" />
<title>Shop - Sky Art Shop</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
2025-12-19 20:44:46 -06:00
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/main.css" />
<link rel="stylesheet" href="/assets/css/navbar.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
2025-12-19 20:44:46 -06:00
<style>
/* Body Reset */
body {
margin: 0;
padding: 0;
background-color: #ffffff;
min-height: 100vh;
}
/* Sticky Banner Container */
.sticky-banner-wrapper {
position: sticky;
top: 0;
z-index: 999;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Shipping Banner */
.shipping-banner {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
text-align: center;
padding: 12px 0;
font-size: 14px;
font-weight: 500;
}
/* Utility Bar - Combined Header and Search */
.utility-bar {
background: #f8f9fa;
padding: 24px 0;
border-bottom: 1px solid #e1e8ed;
}
.utility-bar-content {
display: flex;
justify-content: space-between;
align-items: center;
gap: 40px;
}
.utility-bar-left {
flex: 1;
max-width: 500px;
}
.utility-bar-left h1 {
font-family: "Roboto", sans-serif;
font-size: 28px;
font-weight: 700;
color: #2d3436;
margin: 0 0 8px 0;
line-height: 1.2;
}
.utility-bar-left p {
font-family: "Roboto", sans-serif;
font-size: 15px;
font-weight: 400;
color: #636e72;
margin: 0;
line-height: 1.5;
}
.utility-bar-right {
flex: 0 0 450px;
}
.search-container {
position: relative;
width: 100%;
}
.search-container input {
width: 100%;
padding: 14px 60px 14px 20px;
border: 2px solid #e1e8ed;
border-radius: 50px;
font-family: "Roboto", sans-serif;
font-size: 15px;
transition: all 0.3s;
background: white;
}
.search-container input:focus {
outline: none;
border-color: #ff6b6b;
box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1);
}
.search-container button {
position: absolute;
right: 5px;
top: 50%;
transform: translateY(-50%);
background: #ff6b6b;
color: white;
border: none;
padding: 10px 24px;
border-radius: 50px;
cursor: pointer;
font-family: "Roboto", sans-serif;
font-weight: 600;
font-size: 14px;
transition: background 0.3s;
}
.search-container button:hover {
background: #ee5a52;
}
/* Category Chips */
.categories-section {
padding: 20px 0;
background: white;
border-bottom: 1px solid #e1e8ed;
}
.category-chips {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.category-chip {
padding: 10px 24px;
background: white;
border: 2px solid #e1e8ed;
border-radius: 50px;
cursor: pointer;
font-weight: 500;
transition: all 0.3s;
font-size: 14px;
}
.category-chip:hover {
border-color: #ff6b6b;
color: #ff6b6b;
transform: translateY(-2px);
}
.category-chip.active {
background: #ff6b6b;
border-color: #ff6b6b;
color: white;
}
/* Products Grid */
.shop-main {
min-height: 400px;
}
.shop-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
flex-wrap: wrap;
gap: 16px;
}
.results-count {
font-family: "Roboto", sans-serif;
font-size: 16px;
color: #2d3436;
font-weight: 500;
}
.filter-select {
padding: 10px 16px;
border: 1px solid #e1e8ed;
border-radius: 8px;
font-family: "Roboto", sans-serif;
font-size: 14px;
background: white;
cursor: pointer;
transition: all 0.3s;
}
.filter-select:focus {
outline: none;
border-color: #ff6b6b;
}
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
margin-bottom: 40px;
}
.product-card {
background: white;
border: 1px solid #e1e8ed;
border-radius: 12px;
overflow: hidden;
transition: all 0.3s;
}
.product-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
.product-link {
display: block;
text-decoration: none;
color: inherit;
}
.product-image {
width: 100%;
height: 280px;
overflow: hidden;
background: #f8f9fa;
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.product-card:hover .product-image img {
transform: scale(1.05);
}
.product-card h3 {
font-family: "Roboto", sans-serif;
font-size: 16px;
font-weight: 600;
color: #2d3436;
margin: 16px;
line-height: 1.4;
}
.product-description {
font-family: "Roboto", sans-serif;
font-size: 14px;
color: #636e72;
margin: 0 16px 12px;
line-height: 1.5;
}
.product-card .price {
font-family: "Roboto", sans-serif;
font-size: 20px;
font-weight: 700;
color: #ff6b6b;
margin: 0 16px 16px;
}
.product-color-badge {
display: inline-block;
padding: 4px 12px;
background: #f8f9fa;
border-radius: 12px;
font-size: 12px;
color: #636e72;
margin: 0 16px 12px;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
border: none;
border-radius: 8px;
font-family: "Roboto", sans-serif;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
}
.btn-small {
padding: 8px 12px;
}
.btn-icon {
background: #f8f9fa;
color: #636e72;
border: 1px solid #e1e8ed;
}
.btn-icon:hover {
background: #ff6b6b;
color: white;
border-color: #ff6b6b;
}
#noProducts {
text-align: center;
padding: 60px 20px;
font-family: "Roboto", sans-serif;
font-size: 16px;
color: #636e72;
}
@media (max-width: 968px) {
.utility-bar-content {
flex-direction: column;
gap: 20px;
}
.utility-bar-left {
max-width: 100%;
text-align: center;
}
.utility-bar-left h1 {
font-size: 24px;
}
.utility-bar-left p {
font-size: 14px;
}
.utility-bar-right {
flex: 1;
width: 100%;
}
.category-chips {
overflow-x: auto;
flex-wrap: nowrap;
padding-bottom: 10px;
}
.category-chip {
white-space: nowrap;
}
}
</style>
</head>
2025-12-19 20:44:46 -06:00
<body>
<!-- Modern Navigation (Same as other pages) -->
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home.html" class="brand-link">
<img
src="/uploads/images/8ba675b9-c4e6-41e6-8f14-382b9ee1d019.jpg"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky Art Shop</span>
</a>
</div>
2025-12-19 20:44:46 -06:00
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home.html" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop.html" class="nav-link active">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio.html" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about.html" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog.html" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact.html" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop.html" class="btn-outline">Continue Shopping</a>
</div>
</div>
2025-12-19 20:44:46 -06:00
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state">Your cart is empty</p>
</div>
<div class="dropdown-foot">
<div class="cart-summary">
<span class="summary-label">Subtotal:</span>
<span class="summary-value" id="cartSubtotal">$0.00</span>
</div>
<a href="/checkout.html" class="btn-primary-full"
>Proceed to Checkout</a
>
<a href="/shop.html" class="btn-text">Continue Shopping</a>
</div>
</div>
</div>
2025-12-19 20:44:46 -06:00
<button class="mobile-toggle" id="mobileMenuToggle" aria-label="Menu">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
2025-12-19 20:44:46 -06:00
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home.html" class="mobile-link">Home</a></li>
<li><a href="/shop.html" class="mobile-link">Shop</a></li>
<li><a href="/portfolio.html" class="mobile-link">Portfolio</a></li>
<li><a href="/about.html" class="mobile-link">About</a></li>
<li><a href="/blog.html" class="mobile-link">Blog</a></li>
<li><a href="/contact.html" class="mobile-link">Contact</a></li>
</ul>
</div>
2025-12-19 20:44:46 -06:00
</nav>
<!-- Sticky Banner Wrapper -->
<div class="sticky-banner-wrapper">
<!-- Shipping Banner -->
<div class="shipping-banner">⚡ Free shipping on orders over $50</div>
</div>
2025-12-19 20:44:46 -06:00
<!-- Utility Bar: Header + Search -->
<section class="utility-bar">
<div class="container">
2025-12-19 20:44:46 -06:00
<div class="utility-bar-content">
<!-- Left: Title and Description -->
<div class="utility-bar-left">
<h1>Shop All Products</h1>
<p>
Discover unique art pieces and creative supplies for your next
project
</p>
</div>
<!-- Right: Search Bar -->
<div class="utility-bar-right">
<div class="search-container">
<input
type="search"
placeholder="Search products..."
id="productSearch"
/>
<button type="button">Search</button>
</div>
</div>
</div>
</div>
</section>
2025-12-19 20:44:46 -06:00
<!-- Categories -->
<section class="categories-section">
<div class="container">
2025-12-19 20:44:46 -06:00
<div class="category-chips">
<button class="category-chip active" data-category="all">
All Products
</button>
<button class="category-chip" data-category="paintings">
Paintings
</button>
<button class="category-chip" data-category="prints">Prints</button>
<button class="category-chip" data-category="sculptures">
Sculptures
</button>
<button class="category-chip" data-category="digital">
Digital Art
</button>
<button class="category-chip" data-category="supplies">
Art Supplies
</button>
</div>
</div>
</section>
2025-12-19 20:44:46 -06:00
<!-- Shop Main Content -->
<section class="shop-main" style="padding: 40px 0">
<div class="container">
2025-12-19 20:44:46 -06:00
<div class="shop-layout">
<!-- Products Grid (Main Content) -->
<div class="shop-content" style="width: 100%">
<div class="shop-toolbar">
<p class="results-count" id="resultsCount">Loading products...</p>
<!-- Sort Dropdown -->
<select
class="filter-select"
id="sortSelect"
style="
padding: 8px 12px;
border: 1px solid #e1e8ed;
border-radius: 8px;
"
>
<option value="featured">Featured</option>
<option value="newest">Newest</option>
<option value="price-low">Price: Low to High</option>
<option value="price-high">Price: High to Low</option>
<option value="name">Name: A to Z</option>
</select>
</div>
<div class="products-grid" id="productsGrid">
<!-- Products will be loaded here -->
</div>
<div
id="noProducts"
style="display: none; text-align: center; padding: 40px"
>
<p>No products found.</p>
</div>
<div class="pagination" id="pagination">
<!-- Pagination will be inserted here -->
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
2025-12-19 20:44:46 -06:00
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
2025-12-19 20:44:46 -06:00
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"
><i class="bi bi-instagram"></i
></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"
><i class="bi bi-pinterest"></i
></a>
</div>
</div>
2025-12-19 20:44:46 -06:00
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop.html">All Products</a></li>
<li><a href="/shop.html?category=paintings">Paintings</a></li>
<li><a href="/shop.html?category=prints">Prints</a></li>
<li><a href="/shop.html?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about.html">Our Story</a></li>
<li><a href="/portfolio.html">Portfolio</a></li>
<li><a href="/blog.html">Blog</a></li>
<li><a href="/contact.html">Contact</a></li>
</ul>
</div>
2025-12-19 20:44:46 -06:00
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="#">Shipping Info</a></li>
<li><a href="#">Returns</a></li>
<li><a href="#">FAQ</a></li>
<li><a href="#">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
2025-12-19 20:44:46 -06:00
<p>&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/cart.js"></script>
<script>
2025-12-19 20:44:46 -06:00
// Mobile Menu Toggle (Same as other pages)
const mobileMenuToggle = document.getElementById("mobileMenuToggle");
const mobileMenu = document.getElementById("mobileMenu");
const mobileMenuClose = document.getElementById("mobileMenuClose");
if (mobileMenuToggle) {
mobileMenuToggle.addEventListener("click", () => {
mobileMenu.classList.toggle("active");
});
}
if (mobileMenuClose) {
mobileMenuClose.addEventListener("click", () => {
mobileMenu.classList.remove("active");
});
}
// Load and Display Products
let allProducts = [];
2025-12-19 20:44:46 -06:00
let filteredProducts = [];
let currentCategory = "all";
async function loadProducts() {
try {
const response = await fetch("/api/products");
2025-12-19 20:44:46 -06:00
const data = await response.json();
if (data.success) {
allProducts = data.products || data.data || [];
filteredProducts = allProducts;
displayProducts(filteredProducts);
updateResultsCount(filteredProducts.length);
}
} catch (error) {
console.error("Error loading products:", error);
2025-12-19 20:44:46 -06:00
document.getElementById("resultsCount").textContent =
"Error loading products";
}
}
function displayProducts(products) {
const grid = document.getElementById("productsGrid");
const noProducts = document.getElementById("noProducts");
if (products.length === 0) {
2025-12-19 20:44:46 -06:00
grid.style.display = "none";
noProducts.style.display = "block";
return;
}
2025-12-19 20:44:46 -06:00
grid.style.display = "grid";
noProducts.style.display = "none";
grid.innerHTML = products
2025-12-19 20:44:46 -06:00
.map(
(product) => `
<div class="product-card">
<a href="/product.html?id=${
product.productid || product.id
}" class="product-link">
<div class="product-image">
<img src="${
product.imageurl || "/assets/images/placeholder.jpg"
}" alt="${
product.name
}" loading="lazy" onerror="this.src='/assets/images/placeholder.jpg'" />
2025-12-19 20:44:46 -06:00
</div>
<h3>${product.name}</h3>
${
product.color
? `<span class="product-color-badge">${product.color}</span>`
: ""
}
${
product.shortdescription || product.description
? `<div class="product-description">${
product.shortdescription ||
product.description.substring(0, 100) + "..."
}</div>`
: ""
}
<p class="price">$${parseFloat(product.price).toFixed(2)}</p>
</a>
<div style="display: flex; gap: 0.5rem; margin-top: 0.5rem;">
<button class="btn btn-small btn-icon"
onclick="addToWishlist('${
product.productid || product.id
}', '${product.name.replace(/'/g, "\\'")}', ${
product.price
2025-12-19 20:44:46 -06:00
}, '${product.imageurl}')"
aria-label="Add to wishlist">
<i class="bi bi-heart"></i>
</button>
<button class="btn btn-small btn-icon"
onclick="addToCart('${
product.productid || product.id
}', '${product.name.replace(/'/g, "\\'")}', ${
product.price
2025-12-19 20:44:46 -06:00
}, '${product.imageurl}')"
aria-label="Add to cart">
<i class="bi bi-cart-plus"></i>
</button>
</div>
</div>
`
)
.join("");
}
2025-12-19 20:44:46 -06:00
function updateResultsCount(count) {
document.getElementById(
"resultsCount"
).textContent = `Showing ${count} product${count !== 1 ? "s" : ""}`;
}
2025-12-19 20:44:46 -06:00
// Category Filter
document.querySelectorAll(".category-chip").forEach((chip) => {
chip.addEventListener("click", function () {
document
.querySelectorAll(".category-chip")
.forEach((c) => c.classList.remove("active"));
this.classList.add("active");
2025-12-19 20:44:46 -06:00
currentCategory = this.dataset.category;
2025-12-19 20:44:46 -06:00
if (currentCategory === "all") {
filteredProducts = allProducts;
} else {
filteredProducts = allProducts.filter(
(p) => p.category?.toLowerCase() === currentCategory
);
2025-12-19 20:44:46 -06:00
}
2025-12-19 20:44:46 -06:00
displayProducts(filteredProducts);
updateResultsCount(filteredProducts.length);
});
});
2025-12-19 20:44:46 -06:00
// Sort
document
2025-12-19 20:44:46 -06:00
.getElementById("sortSelect")
?.addEventListener("change", function () {
const sortBy = this.value;
let sorted = [...filteredProducts];
switch (sortBy) {
case "price-low":
sorted.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));
break;
case "price-high":
sorted.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));
break;
case "name":
sorted.sort((a, b) => a.name.localeCompare(b.name));
break;
case "newest":
sorted.sort(
(a, b) => new Date(b.createdat) - new Date(a.createdat)
);
break;
}
displayProducts(sorted);
});
// Price Filter
document
2025-12-19 20:44:46 -06:00
.getElementById("applyPriceFilter")
?.addEventListener("click", function () {
const min =
parseFloat(document.getElementById("priceMin").value) || 0;
const max =
parseFloat(document.getElementById("priceMax").value) || Infinity;
filteredProducts = allProducts.filter((p) => {
const price = parseFloat(p.price);
return price >= min && price <= max;
});
displayProducts(filteredProducts);
updateResultsCount(filteredProducts.length);
});
// Cart Functions
function addToCart(productId) {
// Add to cart logic here
alert("Product added to cart!");
updateCartCount();
}
function addToWishlist(productId) {
// Add to wishlist logic here
alert("Product added to wishlist!");
updateWishlistCount();
}
function quickView(productId) {
// Quick view modal logic
alert("Quick view coming soon!");
}
function updateCartCount() {
// Update cart badge
const count = parseInt(
document.getElementById("cartCount").textContent
);
document.getElementById("cartCount").textContent = count + 1;
}
function updateWishlistCount() {
// Update wishlist badge
const count = parseInt(
document.getElementById("wishlistCount").textContent
);
document.getElementById("wishlistCount").textContent = count + 1;
}
// Search functionality
document
.getElementById("productSearch")
?.addEventListener("input", function (e) {
const searchTerm = e.target.value.toLowerCase();
if (searchTerm === "") {
filteredProducts = allProducts;
} else {
filteredProducts = allProducts.filter(
(p) =>
p.name.toLowerCase().includes(searchTerm) ||
(p.description &&
p.description.toLowerCase().includes(searchTerm))
);
}
displayProducts(filteredProducts);
updateResultsCount(filteredProducts.length);
});
// Initialize
loadProducts();
</script>
2025-12-19 20:44:46 -06:00
</body>
</html>