From 608fae740ac16975405cb5a5474914061ad3caf1 Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 25 Dec 2025 01:32:36 +0700 Subject: [PATCH] Improve Products page with search, filters, and enhanced UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhancements: - Add search bar with real-time filtering - Add category filter buttons (Semua, Webinar, Bootcamp, etc.) - Show result count ("Menampilkan X dari Y produk") - Add clear/reset filters button - Remove booking button from banner (redundant with card) - Improve banner styling with gradient and rounded-xl Consulting card improvements: - Add decorative background element - Better description of service - Add feature icons (Clock, Calendar) - Change price display from "menit" to "sesi" (more premium) - Improve button text ("Booking Jadwal") - Use primary color for price and icons Product card improvements: - Use stripHtml() for description instead of dangerouslySetInnerHTML - Fix spacing: add gap-2 between title and badge, shrink-0 on badge - Larger price display (text-3xl) - Add discount percentage badge for sale items - Color sale price with primary color - Add Check icon for "in cart" state - Green background for added items (bg-green-500) - Items-baseline for better price alignment - Change grid from lg: to xl: for better responsiveness Empty states: - Better empty state with Package icon for no products - New "no results found" state with Search icon - Add reset filter button to empty state Technical: - Add filteredProducts state and logic - Add searchQuery and selectedType states - Add clearFilters function - Import new icons: Clock, Calendar, Check, Search, X - Import Input component for search bar 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/pages/Products.tsx | 221 +++++++++++++++++++++++++++++++---------- 1 file changed, 168 insertions(+), 53 deletions(-) diff --git a/src/pages/Products.tsx b/src/pages/Products.tsx index 8154db2..ece70bd 100644 --- a/src/pages/Products.tsx +++ b/src/pages/Products.tsx @@ -9,7 +9,8 @@ import { useCart } from '@/contexts/CartContext'; import { toast } from '@/hooks/use-toast'; import { Skeleton } from '@/components/ui/skeleton'; import { formatIDR } from '@/lib/format'; -import { Video } from 'lucide-react'; +import { Video, Clock, Calendar, Package, Check, Search, X } from 'lucide-react'; +import { Input } from '@/components/ui/input'; interface Product { id: string; @@ -32,6 +33,8 @@ export default function Products() { const [products, setProducts] = useState([]); const [consultingSettings, setConsultingSettings] = useState(null); const [loading, setLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [selectedType, setSelectedType] = useState('all'); const { addItem, items } = useCart(); useEffect(() => { @@ -93,6 +96,22 @@ export default function Products() { return tmp.textContent || tmp.innerText || ''; }; + // Filter products based on search and type + const filteredProducts = products.filter((product) => { + const matchesSearch = product.title.toLowerCase().includes(searchQuery.toLowerCase()) || + stripHtml(product.description).toLowerCase().includes(searchQuery.toLowerCase()); + const matchesType = selectedType === 'all' || product.type === selectedType; + return matchesSearch && matchesType; + }); + + // Get unique product types for filter + const productTypes = ['all', ...Array.from(new Set(products.map(p => p.type)))]; + + const clearFilters = () => { + setSearchQuery(''); + setSelectedType('all'); + }; + return (
@@ -101,23 +120,73 @@ export default function Products() { {/* Consulting Availability Banner */} {!loading && consultingSettings?.is_consulting_enabled && ( -
-
-
-
-
-

Konsultasi Tersedia!

-

- Booking jadwal konsultasi 1-on-1 dengan mentor • {formatIDR(consultingSettings.consulting_block_price)} / {consultingSettings.consulting_block_duration_minutes} menit -

-
+
+
+
- - - +
+

Konsultasi Tersedia!

+

+ Booking jadwal konsultasi 1-on-1 dengan mentor • {formatIDR(consultingSettings.consulting_block_price)} / {consultingSettings.consulting_block_duration_minutes} menit +

+
+
+ )} + + {/* Search and Filter */} + {!loading && products.length > 0 && ( +
+ {/* Search Bar */} +
+ + setSearchQuery(e.target.value)} + className="pl-10 border-2" + /> + {searchQuery && ( + + )} +
+ + {/* Category Filter */} +
+ Kategori: + {productTypes.map((type) => ( + + ))} + {(searchQuery || selectedType !== 'all') && ( + + )} +
+ + {/* Results Count */} +

+ Menampilkan {filteredProducts.length} dari {products.length} produk +

)} @@ -136,34 +205,47 @@ export default function Products() { ))}
) : ( -
+
{/* Consulting Card - Only show when enabled */} {consultingSettings?.is_consulting_enabled && ( - - -
+ + {/* Decorative element */} +
+ + +
- - Konsultasi + + Konsultasi +
- - Sesi konsultasi pribadi dengan mentor. Pilih waktu dan durasi sesuai kebutuhan Anda. + + Sesi konsultasi pribadi dengan mentor. Diskusikan masalah spesifik dan dapatkan solusi langsung.
- -
- - {formatIDR(consultingSettings.consulting_block_price)} - - - / {consultingSettings.consulting_block_duration_minutes} menit - + +
+
+ + {consultingSettings.consulting_block_duration_minutes} menit per sesi +
+
+ + Pilih jadwal yang tersedia +
+
+ + {formatIDR(consultingSettings.consulting_block_price)} + + / sesi +
-
@@ -171,48 +253,81 @@ export default function Products() { )} {/* Regular Products */} - {products.map((product) => ( + {filteredProducts.map((product) => ( - -
- {product.title} - {getTypeLabel(product.type)} + +
+ {product.title} + + {getTypeLabel(product.type)} +
- + + {stripHtml(product.description)} +
-
+
{product.sale_price ? ( <> - {formatIDR(product.sale_price)} - {formatIDR(product.price)} + + {formatIDR(product.sale_price)} + + + {formatIDR(product.price)} + + + -{Math.round((1 - product.sale_price / product.price) * 100)}% + ) : ( - {formatIDR(product.price)} + {formatIDR(product.price)} )}
- +
))} + {/* Empty State */} + {filteredProducts.length === 0 && products.length > 0 && ( +
+ +

Tidak Ada Produk Ditemukan

+

Coba kata kunci atau kategori lain.

+ +
+ )} + {products.length === 0 && !consultingSettings?.is_consulting_enabled && ( -
-

Belum ada produk tersedia.

+
+ +

Belum Ada Produk

+

Kami sedang mempersiapkan produk menarik untuk Anda.

)}