// ADD THIS LINE FOR FAVICON
echo '';
// Handle category filter
$category = isset($_GET['category']) ? htmlspecialchars(trim($_GET['category'])) : 'all';
$search = isset($_GET['search']) ? htmlspecialchars(trim($_GET['search'])) : '';
// Handle price range filter - set defaults based on database
$price_range = $db->query("SELECT MIN(price) as min_price, MAX(price) as max_price FROM cakes WHERE status = 'active'")->fetch();
$db_min_price = $price_range['min_price'] ?: 0;
$db_max_price = $price_range['max_price'] ?: 20000;
// Get filter values or use defaults
$min_price = isset($_GET['min_price']) ? (int)$_GET['min_price'] : $db_min_price;
$max_price = isset($_GET['max_price']) ? (int)$_GET['max_price'] : $db_max_price;
// Validate price range
if ($min_price < $db_min_price) $min_price = $db_min_price;
if ($max_price > $db_max_price) $max_price = $db_max_price;
if ($min_price > $max_price) $min_price = $db_min_price;
// Check if any filter is active
$filter_active = ($category != 'all' || !empty($search) || $min_price != $db_min_price || $max_price != $db_max_price);
// Build query
$query = "SELECT * FROM cakes WHERE status = 'active'";
$params = [];
if ($category != 'all' && in_array($category, ['birthday', 'wedding', 'kids', 'special', 'cream', 'fondant'])) {
$query .= " AND category = :category";
$params[':category'] = $category;
}
if (!empty($search)) {
$query .= " AND (name LIKE :search OR description LIKE :search)";
$params[':search'] = "%$search%";
}
// Add price range filter
$query .= " AND price >= :min_price AND price <= :max_price";
$params[':min_price'] = $min_price;
$params[':max_price'] = $max_price;
// Sorting - FIXED: Most Popular now uses featured flag and sale status
$sort = isset($_GET['sort']) ? htmlspecialchars(trim($_GET['sort'])) : 'newest';
switch ($sort) {
case 'price_low':
$query .= " ORDER BY CASE WHEN sale_price IS NOT NULL THEN sale_price ELSE price END ASC";
break;
case 'price_high':
$query .= " ORDER BY CASE WHEN sale_price IS NOT NULL THEN sale_price ELSE price END DESC";
break;
case 'name':
$query .= " ORDER BY name ASC";
break;
case 'popular':
// FIXED: Use combination of featured status and sale status for popularity
$query .= " ORDER BY featured DESC, (CASE WHEN sale_price IS NOT NULL THEN 1 ELSE 0 END) DESC, created_at DESC";
break;
default:
$query .= " ORDER BY created_at DESC";
}
// Pagination
$per_page = 12;
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$offset = ($page - 1) * $per_page;
// Get total count with current filters
$count_query = "SELECT COUNT(*) as total FROM cakes WHERE status = 'active'";
$count_params = [];
if ($category != 'all' && in_array($category, ['birthday', 'wedding', 'kids', 'special', 'cream', 'fondant'])) {
$count_query .= " AND category = :category";
$count_params[':category'] = $category;
}
if (!empty($search)) {
$count_query .= " AND (name LIKE :search OR description LIKE :search)";
$count_params[':search'] = "%$search%";
}
// Add price range to count
$count_query .= " AND price >= :min_price AND price <= :max_price";
$count_params[':min_price'] = $min_price;
$count_params[':max_price'] = $max_price;
$count_stmt = $db->prepare($count_query);
foreach ($count_params as $key => $value) {
$count_stmt->bindValue($key, $value);
}
$count_stmt->execute();
$total_rows = $count_stmt->fetch()['total'];
$total_pages = ceil($total_rows / $per_page);
// Add pagination to main query
$query .= " LIMIT :limit OFFSET :offset";
$params[':limit'] = $per_page;
$params[':offset'] = $offset;
// Execute query
$stmt = $db->prepare($query);
foreach ($params as $key => $value) {
if ($key == ':limit' || $key == ':offset') {
$stmt->bindValue($key, $value, PDO::PARAM_INT);
} else {
$stmt->bindValue($key, $value);
}
}
$stmt->execute();
$cakes = $stmt->fetchAll();
// Get category counts
$category_counts = $db->query("SELECT category, COUNT(*) as count FROM cakes WHERE status = 'active' GROUP BY category")->fetchAll();
?>
Shop - Pick a Pie