- {/* Review 1 */}
-
-
-
- JD
-
-
-
- John Doe
- • 2 days ago
- Verified Purchase
-
-
- {[1, 2, 3, 4, 5].map((star) => (
-
-
-
- ))}
-
-
- Absolutely love this product! The quality exceeded my expectations and it arrived quickly.
- The packaging was also very professional. Highly recommend!
-
-
Helpful (24)
+
+
setActiveTab(activeTab === 'reviews' ? '' : 'reviews')}
+ className="w-full flex items-center justify-between p-5 bg-white hover:bg-gray-50 transition-colors"
+ >
+
+
Customer Reviews
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+
+
+ ))}
+
+ {product.average_rating || 0} ({product.review_count || 0} reviews)
+
-
- {/* Review 2 */}
-
-
-
- SM
-
-
-
- Sarah Miller
- • 1 week ago
- Verified Purchase
-
-
- {[1, 2, 3, 4, 5].map((star) => (
-
-
-
- ))}
-
-
- Great value for money. Works exactly as described. Customer service was also very responsive
- when I had questions before purchasing.
-
-
Helpful (18)
-
-
-
-
- {/* Review 3 */}
-
-
-
- MJ
-
-
-
- Michael Johnson
- • 2 weeks ago
- Verified Purchase
-
-
- {[1, 2, 3, 4, 5].map((star) => (
-
-
-
- ))}
-
-
- Perfect! This is my third purchase and I keep coming back. The consistency in quality is impressive.
- Will definitely buy again.
-
-
Helpful (32)
-
-
-
-
-
-
- Load More Reviews
+
+
+
+ {activeTab === 'reviews' && (
+
+ {/* Review Summary */}
+
+
+
5.0
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+
+
+ ))}
+
+
Based on 128 reviews
+
+
+ {[5, 4, 3, 2, 1].map((rating) => (
+
+
{rating} ★
+
+
{rating === 5 ? '122' : rating === 4 ? '5' : '1'}
+
+ ))}
+
+
+
+ {/* Sample Reviews */}
+
+ {/* Review 1 */}
+
+
+
+ JD
+
+
+
+ John Doe
+ • 2 days ago
+ Verified Purchase
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+
+
+ ))}
+
+
+ Absolutely love this product! The quality exceeded my expectations and it arrived quickly.
+ The packaging was also very professional. Highly recommend!
+
+
Helpful (24)
+
+
+
+
+ {/* Review 2 */}
+
+
+
+ SM
+
+
+
+ Sarah Miller
+ • 1 week ago
+ Verified Purchase
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+
+
+ ))}
+
+
+ Great value for money. Works exactly as described. Customer service was also very responsive
+ when I had questions before purchasing.
+
+
Helpful (18)
+
+
+
+
+ {/* Review 3 */}
+
+
+
+ MJ
+
+
+
+ Michael Johnson
+ • 2 weeks ago
+ Verified Purchase
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+
+
+ ))}
+
+
+ Perfect! This is my third purchase and I keep coming back. The consistency in quality is impressive.
+ Will definitely buy again.
+
+
Helpful (32)
+
+
+
+
+
+
+ Load More Reviews
+
+
+ )}
- )}
-
- ))}
+ ))}
{/* Related Products */}
diff --git a/customer-spa/src/pages/Shop/index.tsx b/customer-spa/src/pages/Shop/index.tsx
index 2cc72e2..df08bc5 100644
--- a/customer-spa/src/pages/Shop/index.tsx
+++ b/customer-spa/src/pages/Shop/index.tsx
@@ -10,6 +10,7 @@ import { ProductCard } from '@/components/ProductCard';
import { toast } from 'sonner';
import { useTheme, useLayout } from '@/contexts/ThemeContext';
import { useShopSettings } from '@/hooks/useAppearanceSettings';
+import SEOHead from '@/components/SEOHead';
import type { ProductsResponse, ProductCategory, Product } from '@/types/product';
export default function Shop() {
@@ -22,25 +23,25 @@ export default function Shop() {
const [category, setCategory] = useState('');
const [sortBy, setSortBy] = useState('');
const { addItem } = useCartStore();
-
+
// Map grid columns setting to Tailwind classes (responsive)
- const gridCols = typeof shopLayout.grid_columns === 'object'
- ? shopLayout.grid_columns
+ const gridCols = typeof shopLayout.grid_columns === 'object'
+ ? shopLayout.grid_columns
: { mobile: '2', tablet: '3', desktop: '4' };
-
+
// Map to actual Tailwind classes (can't use template literals due to purging)
const mobileClass = {
'1': 'grid-cols-1',
'2': 'grid-cols-2',
'3': 'grid-cols-3',
}[gridCols.mobile] || 'grid-cols-2';
-
+
const tabletClass = {
'2': 'md:grid-cols-2',
'3': 'md:grid-cols-3',
'4': 'md:grid-cols-4',
}[gridCols.tablet] || 'md:grid-cols-3';
-
+
const desktopClass = {
'2': 'lg:grid-cols-2',
'3': 'lg:grid-cols-3',
@@ -48,22 +49,22 @@ export default function Shop() {
'5': 'lg:grid-cols-5',
'6': 'lg:grid-cols-6',
}[gridCols.desktop] || 'lg:grid-cols-4';
-
+
const gridColsClass = `${mobileClass} ${tabletClass} ${desktopClass}`;
-
+
// Masonry column classes
const masonryMobileClass = {
'1': 'columns-1',
'2': 'columns-2',
'3': 'columns-3',
}[gridCols.mobile] || 'columns-2';
-
+
const masonryTabletClass = {
'2': 'md:columns-2',
'3': 'md:columns-3',
'4': 'md:columns-4',
}[gridCols.tablet] || 'md:columns-3';
-
+
const masonryDesktopClass = {
'2': 'lg:columns-2',
'3': 'lg:columns-3',
@@ -71,9 +72,9 @@ export default function Shop() {
'5': 'lg:columns-5',
'6': 'lg:columns-6',
}[gridCols.desktop] || 'lg:columns-4';
-
+
const masonryColsClass = `${masonryMobileClass} ${masonryTabletClass} ${masonryDesktopClass}`;
-
+
const isMasonry = shopLayout.grid_style === 'masonry';
// Fetch products
@@ -99,7 +100,7 @@ export default function Shop() {
product_id: product.id,
quantity: 1,
});
-
+
// Add to local cart store
addItem({
key: `${product.id}`,
@@ -111,7 +112,7 @@ export default function Shop() {
virtual: product.virtual,
downloadable: product.downloadable,
});
-
+
toast.success(`${product.name} added to cart!`, {
action: {
label: 'View Cart',
@@ -126,6 +127,11 @@ export default function Shop() {
return (
+ {/* SEO Meta Tags for Social Sharing */}
+
{/* Header */}
Shop
diff --git a/includes/Frontend/TemplateOverride.php b/includes/Frontend/TemplateOverride.php
index 42de655..a41c137 100644
--- a/includes/Frontend/TemplateOverride.php
+++ b/includes/Frontend/TemplateOverride.php
@@ -16,10 +16,21 @@ class TemplateOverride
// Register rewrite rules for BrowserRouter SEO (must be on 'init')
add_action('init', [__CLASS__, 'register_spa_rewrite_rules']);
- // Flush rewrite rules when appearance settings are updated
- add_action('update_option_woonoow_appearance_settings', function() {
- flush_rewrite_rules();
- });
+ // Flush rewrite rules when relevant settings change
+ add_action('update_option_woonoow_appearance_settings', function($old_value, $new_value) {
+ $old_general = $old_value['general'] ?? [];
+ $new_general = $new_value['general'] ?? [];
+
+ // Only flush if spa_mode, spa_page, or use_browser_router changed
+ $needs_flush =
+ ($old_general['spa_mode'] ?? '') !== ($new_general['spa_mode'] ?? '') ||
+ ($old_general['spa_page'] ?? '') !== ($new_general['spa_page'] ?? '') ||
+ ($old_general['use_browser_router'] ?? true) !== ($new_general['use_browser_router'] ?? true);
+
+ if ($needs_flush) {
+ flush_rewrite_rules();
+ }
+ }, 10, 2);
// Redirect WooCommerce pages to SPA routes early (before template loads)
add_action('template_redirect', [__CLASS__, 'redirect_wc_pages_to_spa'], 5);