mirror of
https://github.com/myronblair/tomsjavajive
synced 2026-06-30 17:50:32 -05:00
Fix product images, add-to-cart, and add Sub Categories filter
- Add display:block to .product-card-image so padding-top aspect ratio works on anchor tags - Add Cache-Control: no-transform header to disable Cloudflare Rocket Loader (was deferring main.js and breaking add-to-cart click handlers) - Add Sub Categories filter row on shop page using product_types table - Show category · sub-category on product cards - Add Sub Categories section to footer - Preserve subcat param across category/sort filter links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -338,6 +338,7 @@ img {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.product-card-image {
|
.product-card-image {
|
||||||
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: 100%;
|
padding-top: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -24,6 +24,17 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>Sub Categories</h4>
|
||||||
|
<ul class="footer-links">
|
||||||
|
<?php
|
||||||
|
$footerTypes = db()->fetchAll("SELECT type_id, name FROM product_types WHERE is_active=1 ORDER BY sort_order ASC");
|
||||||
|
foreach ($footerTypes as $ft): ?>
|
||||||
|
<li><a href="/shop.php?subcat=<?= urlencode($ft['type_id']) ?>"><?= htmlspecialchars($ft['name']) ?></a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4>Company</h4>
|
<h4>Company</h4>
|
||||||
<ul class="footer-links">
|
<ul class="footer-links">
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate, no-transform');
|
||||||
|
|
||||||
require_once __DIR__ . '/db.php';
|
require_once __DIR__ . '/db.php';
|
||||||
require_once __DIR__ . '/../config/config.php';
|
require_once __DIR__ . '/../config/config.php';
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ require_once __DIR__ . '/includes/functions.php';
|
|||||||
|
|
||||||
// Get filters
|
// Get filters
|
||||||
$category = $_GET['category'] ?? '';
|
$category = $_GET['category'] ?? '';
|
||||||
|
$subcat = $_GET['subcat'] ?? '';
|
||||||
$search = $_GET['search'] ?? '';
|
$search = $_GET['search'] ?? '';
|
||||||
$sort = $_GET['sort'] ?? 'newest';
|
$sort = $_GET['sort'] ?? 'newest';
|
||||||
$page = max(1, intval($_GET['page'] ?? 1));
|
$page = max(1, intval($_GET['page'] ?? 1));
|
||||||
@@ -21,6 +22,11 @@ if ($category) {
|
|||||||
$params['category'] = $category;
|
$params['category'] = $category;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($subcat) {
|
||||||
|
$where[] = 'product_type_id = :subcat';
|
||||||
|
$params['subcat'] = $subcat;
|
||||||
|
}
|
||||||
|
|
||||||
if ($search) {
|
if ($search) {
|
||||||
$where[] = '(name LIKE :search OR description LIKE :search)';
|
$where[] = '(name LIKE :search OR description LIKE :search)';
|
||||||
$params['search'] = '%' . $search . '%';
|
$params['search'] = '%' . $search . '%';
|
||||||
@@ -42,7 +48,7 @@ $pagination = paginate($totalProducts, $page, 12);
|
|||||||
|
|
||||||
// Get products
|
// Get products
|
||||||
$products = db()->fetchAll(
|
$products = db()->fetchAll(
|
||||||
"SELECT * FROM products WHERE {$whereClause} ORDER BY {$orderBy} LIMIT :limit OFFSET :offset",
|
"SELECT p.*, pt.name AS type_name, pt.type_id AS type_slug FROM products p LEFT JOIN product_types pt ON p.product_type_id = pt.type_id WHERE {$whereClause} ORDER BY {$orderBy} LIMIT :limit OFFSET :offset",
|
||||||
array_merge($params, ['limit' => $pagination['per_page'], 'offset' => $pagination['offset']])
|
array_merge($params, ['limit' => $pagination['per_page'], 'offset' => $pagination['offset']])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -71,15 +77,29 @@ $productTypesList = db()->fetchAll("SELECT type_id, name, slug FROM product_type
|
|||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- Filters Bar -->
|
<!-- Filters Bar -->
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; margin-bottom: 2rem;">
|
<div style="display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 1rem; margin-bottom: 2rem;">
|
||||||
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
<div style="display: flex; flex-direction: column; gap: 0.75rem;">
|
||||||
<a href="/shop.php" class="btn <?= !$category ? 'btn-primary' : 'btn-secondary' ?>">All</a>
|
<div style="display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center;">
|
||||||
<?php foreach ($categories as $cat): ?>
|
<a href="/shop.php<?= $subcat ? '?subcat=' . urlencode($subcat) : '' ?>" class="btn <?= !$category ? 'btn-primary' : 'btn-secondary' ?>">All</a>
|
||||||
<a href="/shop.php?category=<?= urlencode($cat['category']) ?>"
|
<?php foreach ($categories as $cat): ?>
|
||||||
class="btn <?= $category === $cat['category'] ? 'btn-primary' : 'btn-secondary' ?>">
|
<a href="/shop.php?category=<?= urlencode($cat['category']) ?><?= $subcat ? '&subcat=' . urlencode($subcat) : '' ?>"
|
||||||
<?= htmlspecialchars(ucfirst($cat['category'])) ?>
|
class="btn <?= $category === $cat['category'] ? 'btn-primary' : 'btn-secondary' ?>">
|
||||||
</a>
|
<?= htmlspecialchars(ucfirst($cat['category'])) ?>
|
||||||
<?php endforeach; ?>
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php if (!empty($productTypesList)): ?>
|
||||||
|
<div style="display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center;">
|
||||||
|
<span class="text-muted" style="font-size: 0.85rem; font-weight: 600; white-space: nowrap;">Sub Categories:</span>
|
||||||
|
<a href="/shop.php<?= $category ? '?category=' . urlencode($category) : '' ?>" class="btn btn-sm <?= !$subcat ? 'btn-primary' : 'btn-secondary' ?>">All</a>
|
||||||
|
<?php foreach ($productTypesList as $pt): ?>
|
||||||
|
<a href="/shop.php?subcat=<?= urlencode($pt['type_id']) ?><?= $category ? '&category=' . urlencode($category) : '' ?>"
|
||||||
|
class="btn btn-sm <?= $subcat === $pt['type_id'] ? 'btn-primary' : 'btn-secondary' ?>">
|
||||||
|
<?= htmlspecialchars($pt['name']) ?>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; gap: 1rem; align-items: center;">
|
<div style="display: flex; gap: 1rem; align-items: center;">
|
||||||
@@ -87,24 +107,39 @@ $productTypesList = db()->fetchAll("SELECT type_id, name, slug FROM product_type
|
|||||||
<?php if ($category): ?>
|
<?php if ($category): ?>
|
||||||
<input type="hidden" name="category" value="<?= htmlspecialchars($category) ?>">
|
<input type="hidden" name="category" value="<?= htmlspecialchars($category) ?>">
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if ($subcat): ?>
|
||||||
|
<input type="hidden" name="subcat" value="<?= htmlspecialchars($subcat) ?>">
|
||||||
|
<?php endif; ?>
|
||||||
<input type="text" name="search" class="form-input" placeholder="Search..."
|
<input type="text" name="search" class="form-input" placeholder="Search..."
|
||||||
value="<?= htmlspecialchars($search) ?>" style="width: 200px;">
|
value="<?= htmlspecialchars($search) ?>" style="width: 200px;">
|
||||||
<button type="submit" class="btn btn-secondary"><i class="fas fa-search"></i></button>
|
<button type="submit" class="btn btn-secondary"><i class="fas fa-search"></i></button>
|
||||||
</form>
|
</form>
|
||||||
|
<?php
|
||||||
|
$filterQs = http_build_query(array_filter(['category' => $category, 'subcat' => $subcat]));
|
||||||
|
$filterQs = $filterQs ? '&' . $filterQs : '';
|
||||||
|
?>
|
||||||
<select onchange="window.location.href=this.value" class="form-select" style="width: auto;">
|
<select onchange="window.location.href=this.value" class="form-select" style="width: auto;">
|
||||||
<option value="/shop.php?sort=newest<?= $category ? '&category=' . urlencode($category) : '' ?>" <?= $sort === 'newest' ? 'selected' : '' ?>>Newest</option>
|
<option value="/shop.php?sort=newest<?= $filterQs ?>" <?= $sort === 'newest' ? 'selected' : '' ?>>Newest</option>
|
||||||
<option value="/shop.php?sort=price_low<?= $category ? '&category=' . urlencode($category) : '' ?>" <?= $sort === 'price_low' ? 'selected' : '' ?>>Price: Low to High</option>
|
<option value="/shop.php?sort=price_low<?= $filterQs ?>" <?= $sort === 'price_low' ? 'selected' : '' ?>>Price: Low to High</option>
|
||||||
<option value="/shop.php?sort=price_high<?= $category ? '&category=' . urlencode($category) : '' ?>" <?= $sort === 'price_high' ? 'selected' : '' ?>>Price: High to Low</option>
|
<option value="/shop.php?sort=price_high<?= $filterQs ?>" <?= $sort === 'price_high' ? 'selected' : '' ?>>Price: High to Low</option>
|
||||||
<option value="/shop.php?sort=name<?= $category ? '&category=' . urlencode($category) : '' ?>" <?= $sort === 'name' ? 'selected' : '' ?>>Name</option>
|
<option value="/shop.php?sort=name<?= $filterQs ?>" <?= $sort === 'name' ? 'selected' : '' ?>>Name</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Results count -->
|
<!-- Results count -->
|
||||||
|
<?php
|
||||||
|
$subcatName = '';
|
||||||
|
if ($subcat) {
|
||||||
|
foreach ($productTypesList as $pt) {
|
||||||
|
if ($pt['type_id'] === $subcat) { $subcatName = $pt['name']; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
<p class="text-muted" style="margin-bottom: 1.5rem;">
|
<p class="text-muted" style="margin-bottom: 1.5rem;">
|
||||||
Showing <?= count($products) ?> of <?= $totalProducts ?> products
|
Showing <?= count($products) ?> of <?= $totalProducts ?> products
|
||||||
<?= $category ? ' in ' . htmlspecialchars(ucfirst($category)) : '' ?>
|
<?= $category ? ' in ' . htmlspecialchars(ucfirst($category)) : '' ?>
|
||||||
|
<?= $subcatName ? ' · ' . htmlspecialchars($subcatName) : '' ?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Product Grid -->
|
<!-- Product Grid -->
|
||||||
@@ -132,8 +167,13 @@ $productTypesList = db()->fetchAll("SELECT type_id, name, slug FROM product_type
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</a>
|
</a>
|
||||||
<div class="product-card-body">
|
<div class="product-card-body">
|
||||||
<?php if ($product['category']): ?>
|
<?php if ($product['category'] || !empty($product['type_name'])): ?>
|
||||||
<div class="product-card-category"><?= htmlspecialchars($product['category']) ?></div>
|
<div class="product-card-category">
|
||||||
|
<?= htmlspecialchars($product['category'] ?? '') ?>
|
||||||
|
<?php if (!empty($product['type_name'])): ?>
|
||||||
|
<?= $product['category'] ? ' · ' : '' ?><?= htmlspecialchars($product['type_name']) ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<h3 class="product-card-title">
|
<h3 class="product-card-title">
|
||||||
<a href="/product.php?id=<?= $product['product_id'] ?>"><?= htmlspecialchars($product['name']) ?></a>
|
<a href="/product.php?id=<?= $product['product_id'] ?>"><?= htmlspecialchars($product['name']) ?></a>
|
||||||
|
|||||||
Reference in New Issue
Block a user