+ {/* Top Bar Filters (Basic Layout) */}
+ {!isRichSidebar && (elements.search_bar || elements.category_filter || elements.sort_dropdown) && (
+
+ {/* Search */}
+ {elements.search_bar && (
+
+
+ setSearch(e.target.value)}
+ className="!pl-10 pr-10"
+ />
+ {search && (
+
+ )}
+
+ )}
+
+ {/* Category Filter */}
+ {elements.category_filter && categories && categories.length > 0 && (
+
+
+
+
+ )}
+
+ {/* Sort Dropdown */}
+ {elements.sort_dropdown && (
+
+
+
)}
)}
- {/* Category Filter */}
- {elements.category_filter && categories && categories.length > 0 && (
-
- )}
-
- {/* Sort Dropdown */}
- {elements.sort_dropdown && (
-
+ {/* Sort Dropdown (Rich Layout) */}
+ {isRichSidebar && elements.sort_dropdown && (
+
)}
-
- {[...Array(8)].map((_, i) => (
-
-
-
-
+ {/* Products Grid */}
+ {productsLoading ? (
+
+ {[...Array(8)].map((_, i) => (
+
+ ))}
- ))}
-
- ) : productsData?.products && productsData.products.length > 0 ? (
- <>
-
- {productsData.products.map((product: any) => (
-
- ))}
-
+ ) : productsData?.products && productsData.products.length > 0 ? (
+ <>
+ {isMasonry ? (
+
+ {(() => {
+ const currentCols = parseInt(gridCols[breakpoint] || (breakpoint === 'mobile' ? '2' : breakpoint === 'tablet' ? '3' : '4'));
+ // Use a safe column count fallback (e.g. at least 1)
+ const cols = Math.max(1, currentCols);
+ const masonryColumns: any[][] = Array.from({ length: cols }, () => []);
+ productsData.products.forEach((p: any, i: number) => {
+ masonryColumns[i % cols].push(p);
+ });
+ return masonryColumns.map((col, colIndex) => (
+
+ {col.map((product) => (
+
+ ))}
+
+ ));
+ })()}
+
+ ) : (
+
+ {productsData.products.map((product: any) => (
+
+ ))}
+
+ )}
- {/* Pagination */}
- {productsData.total_pages > 1 && (
-
-
-
- Page {page} of {productsData.total_pages}
-
-
+ {/* Pagination */}
+ {productsData.total_pages > 1 && (
+
+
+
+ Page {page} of {productsData.total_pages}
+
+
+
+ )}
+ >
+ ) : (
+
+
No products found
+ {!isRichSidebar && (search || category || minPrice || maxPrice) && (
+
+ )}
)}
- >
- ) : (
-
-
No products found
- {(search || category) && (
-
- )}
- )}
+
);
}
diff --git a/includes/Admin/AppearanceController.php b/includes/Admin/AppearanceController.php
index c774bf5..4c692e1 100644
--- a/includes/Admin/AppearanceController.php
+++ b/includes/Admin/AppearanceController.php
@@ -356,6 +356,7 @@ class AppearanceController
'card_style' => sanitize_text_field($data['layout']['card_style'] ?? 'card'),
'aspect_ratio' => sanitize_text_field($data['layout']['aspect_ratio'] ?? 'square'),
'card_text_align' => sanitize_text_field($data['layout']['card_text_align'] ?? 'left'),
+ 'filter_layout' => sanitize_text_field($data['layout']['filter_layout'] ?? 'basic'),
],
'elements' => [
'category_filter' => (bool) ($data['elements']['category_filter'] ?? true),
@@ -588,6 +589,7 @@ class AppearanceController
'grid_columns' => '3',
'card_style' => 'card',
'aspect_ratio' => 'square',
+ 'filter_layout' => 'basic',
],
'elements' => [
'category_filter' => true,
diff --git a/includes/Frontend/ShopController.php b/includes/Frontend/ShopController.php
index dec4283..16923d5 100644
--- a/includes/Frontend/ShopController.php
+++ b/includes/Frontend/ShopController.php
@@ -54,6 +54,14 @@ class ShopController
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
],
+ 'min_price' => [
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ ],
+ 'max_price' => [
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ ],
],
]);
@@ -106,6 +114,8 @@ class ShopController
$slug = $request->get_param('slug');
$include = $request->get_param('include');
$exclude = $request->get_param('exclude');
+ $min_price = $request->get_param('min_price');
+ $max_price = $request->get_param('max_price');
$args = [
'post_type' => 'product',
@@ -152,6 +162,30 @@ class ShopController
$args['s'] = $search;
}
+ // Add price filter
+ if ($min_price !== '' || $max_price !== '') {
+ $price_query = [
+ 'key' => '_price',
+ 'type' => 'NUMERIC',
+ ];
+
+ if ($min_price !== '' && $max_price !== '') {
+ $price_query['compare'] = 'BETWEEN';
+ $price_query['value'] = [(float)$min_price, (float)$max_price];
+ } elseif ($min_price !== '') {
+ $price_query['compare'] = '>=';
+ $price_query['value'] = (float)$min_price;
+ } else {
+ $price_query['compare'] = '<=';
+ $price_query['value'] = (float)$max_price;
+ }
+
+ if (!isset($args['meta_query'])) {
+ $args['meta_query'] = [];
+ }
+ $args['meta_query'][] = $price_query;
+ }
+
$query = new \WP_Query($args);
// Check if this is a single product request (by slug)