diff --git a/app/Http/Controllers/HomepageController.php b/app/Http/Controllers/HomepageController.php index 94e6a39..e911083 100644 --- a/app/Http/Controllers/HomepageController.php +++ b/app/Http/Controllers/HomepageController.php @@ -9,10 +9,28 @@ class HomepageController extends Controller { public function __invoke() { + $search = request('search'); + $categorySlug = request('category'); + return inertia('homepage', [ - 'categories' => Category::all(), - 'bestSellers' => Product::with(['categories', 'prices'])->active()->latest()->take(4)->get(), - 'topSellingProducts' => Product::with(['categories', 'prices'])->withCount('orderItems')->active()->orderBy('order_items_count', 'desc')->take(3)->get(), + 'categories' => Category::active()->get(), + 'bestSellers' => Product::with(['categories' => fn ($q) => $q->active(), 'prices']) + ->when($search, function ($query, $search) { + $query->where(function ($q) use ($search) { + $q->where('name', 'like', "%{$search}%") + ->orWhere('description', 'like', "%{$search}%"); + }); + }) + ->when($categorySlug, function ($query, $categorySlug) { + $query->whereHas('categories', function ($q) use ($categorySlug) { + $q->where('categories.slug', $categorySlug); + }); + }) + ->active() + ->latest() + ->paginate(12) + ->withQueryString(), + 'topSellingProducts' => Product::with(['categories' => fn ($q) => $q->active(), 'prices'])->withCount('orderItems')->active()->orderBy('order_items_count', 'desc')->take(3)->get(), ]); } } diff --git a/resources/js/pages/homepage.tsx b/resources/js/pages/homepage.tsx index 8088293..c083206 100644 --- a/resources/js/pages/homepage.tsx +++ b/resources/js/pages/homepage.tsx @@ -1,12 +1,62 @@ -import { Link } from '@inertiajs/react'; -import { ArrowRight, Facebook, Instagram, Twitter, X, Youtube } from 'lucide-react'; -import { useEffect, useState } from 'react'; import { formatCurrency } from '@/lib/formatters'; +import { Link, router } from '@inertiajs/react'; +import { ArrowRight, Facebook, Instagram, Search, X } from 'lucide-react'; +import { useEffect, useState } from 'react'; -export default function Homepage({ categories = [], bestSellers = [], topSellingProducts = [] }: { categories: any[], bestSellers: any[], topSellingProducts: any[] }) { +export default function Homepage({ categories = [], bestSellers, topSellingProducts = [] }: { categories: any[], bestSellers: any, topSellingProducts: any[] }) { const [isMenuOpen, setIsMenuOpen] = useState(false); const [isScrolled, setIsScrolled] = useState(false); const [selectedProduct, setSelectedProduct] = useState(null); + const [allProducts, setAllProducts] = useState(bestSellers.data); + const [search, setSearch] = useState(''); + const [selectedCategorySlug, setSelectedCategorySlug] = useState(''); + + useEffect(() => { + const timer = setTimeout(() => { + router.get(window.location.pathname, { search, category: selectedCategorySlug }, { + preserveState: true, + preserveScroll: true, + only: ['bestSellers'], + onSuccess: (page: any) => { + setAllProducts(page.props.bestSellers.data); + } + }); + }, 500); + + return () => clearTimeout(timer); + }, [search]); + + useEffect(() => { + router.get(window.location.pathname, { search, category: selectedCategorySlug }, { + preserveState: true, + preserveScroll: true, + only: ['bestSellers'], + onSuccess: (page: any) => { + setAllProducts(page.props.bestSellers.data); + } + }); + }, [selectedCategorySlug]); + + useEffect(() => { + if (bestSellers.current_page > 1) { + setAllProducts(prev => { + // Prevent duplicates if data already exists + const existingIds = new Set(prev.map(p => p.id)); + const newProducts = bestSellers.data.filter((p: any) => !existingIds.has(p.id)); + return [...prev, ...newProducts]; + }); + } + }, [bestSellers]); + + const loadMore = () => { + if (bestSellers.next_page_url) { + router.get(bestSellers.next_page_url, {}, { + preserveState: true, + preserveScroll: true, + only: ['bestSellers'], + }); + } + }; useEffect(() => { const handleScroll = () => { @@ -39,7 +89,7 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling }; }, []); - const scrollToSection = (e: React.MouseEvent, id: string) => { + const scrollToSection = (e: React.MouseEvent, id: string) => { e.preventDefault(); const element = document.querySelector(id); if (element) { @@ -103,10 +153,21 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling
- {categories.map((cat) => ( - ))} {categories.length === 0 && ( @@ -124,9 +185,8 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling

Ikuti Kami

- + -
@@ -134,7 +194,7 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling {/* Hero Image */}
- Model + Model
@@ -147,27 +207,27 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling

Tingkatkan gaya harian Anda dengan koleksi esensial yang dibuat dengan ketelitian dan kualitas tinggi. Mulai dari bahan berkelanjutan hingga desain yang tak lekang oleh waktu.

- +
{topSellingProducts.map((product, i) => ( -
setSelectedProduct(product)} > - {product.name}
))} {topSellingProducts.length === 0 && (
- {[1,2,3].map(i => ( + {[1, 2, 3].map(i => (
))}
@@ -182,11 +242,38 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling {/* Best Sellers Section */}
-
+

Produk Terlaris

- scrollToSection(e, '#product')} className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-widest hover:opacity-70 transition-all"> - Semua Produk - +
+ {/* Category Filter */} +
+ +
+
+
+
+ + {/* Search Input */} +
+ + setSearch(e.target.value)} + className="border border-[#1e4a6d]/20 bg-transparent py-2 pl-10 pr-4 text-[10px] font-bold uppercase tracking-widest outline-none transition-all focus:border-[#1e4a6d] w-full sm:w-[200px]" + /> +
+
@@ -194,16 +281,16 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling
- {bestSellers.map((item, idx) => ( + {allProducts.map((item, idx) => (
-
setSelectedProduct(item)} > - {item.name}
@@ -221,12 +308,37 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling
))} - {bestSellers.length === 0 && ( -
- Produk belum tersedia + {allProducts.length === 0 && ( +
+
+ +
+

Produk tidak ditemukan

+

Coba gunakan kata kunci lain atau periksa ejaan Anda.

+
)}
+ + {bestSellers.next_page_url && ( +
+ +
+ )}
@@ -297,7 +409,7 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling

- +
@@ -362,31 +474,29 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling
- +
)} {/* Product Detail Modal */} -
-
setSelectedProduct(null)}>
-
+
setSelectedProduct(null)}>
+
- +
{/* Product Images */}
- {selectedProduct?.name}
@@ -413,7 +523,7 @@ export default function Homepage({ categories = [], bestSellers = [], topSelling

{selectedProduct?.name}

{formatCurrency(selectedProduct?.retail_price || 0)}

- +

Deskripsi