feat: add active modal image state and thumbnail update logic to product display
This commit is contained in:
parent
530d2cbbcb
commit
b7f3953a56
@ -10,6 +10,13 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
const [allProducts, setAllProducts] = useState<any[]>(bestSellers.data);
|
||||
const [search, setSearch] = useState('');
|
||||
const [selectedCategorySlug, setSelectedCategorySlug] = useState('');
|
||||
const [activeModalImage, setActiveModalImage] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedProduct) {
|
||||
setActiveModalImage(selectedProduct?.thumbnail_url);
|
||||
}
|
||||
}, [selectedProduct]);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
@ -154,20 +161,18 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
<div className="relative mb-8">
|
||||
<div className="custom-scrollbar flex max-h-[300px] flex-col overflow-y-auto border-y border-[#1e4a6d]/20">
|
||||
{categories.map((cat: any) => (
|
||||
<button
|
||||
key={cat.id}
|
||||
<button
|
||||
key={cat.id}
|
||||
onClick={(e) => {
|
||||
setSelectedCategorySlug(cat.slug);
|
||||
scrollToSection(e, '#product');
|
||||
}}
|
||||
className={`group flex items-center justify-between border-b border-[#1e4a6d]/10 px-4 py-4 text-left text-xs font-bold uppercase tracking-wider transition-all hover:bg-[#1e4a6d] hover:text-white last:border-0 ${
|
||||
selectedCategorySlug === cat.slug ? 'bg-[#1e4a6d] text-white' : ''
|
||||
}`}
|
||||
className={`group flex items-center justify-between border-b border-[#1e4a6d]/10 px-4 py-4 text-left text-xs font-bold uppercase tracking-wider transition-all hover:bg-[#1e4a6d] hover:text-white last:border-0 ${selectedCategorySlug === cat.slug ? 'bg-[#1e4a6d] text-white' : ''
|
||||
}`}
|
||||
>
|
||||
{cat.name}
|
||||
<ArrowRight size={14} className={`transition-all group-hover:translate-x-1 group-hover:opacity-100 ${
|
||||
selectedCategorySlug === cat.slug ? 'opacity-100 translate-x-1' : 'opacity-0'
|
||||
}`} />
|
||||
<ArrowRight size={14} className={`transition-all group-hover:translate-x-1 group-hover:opacity-100 ${selectedCategorySlug === cat.slug ? 'opacity-100 translate-x-1' : 'opacity-0'
|
||||
}`} />
|
||||
</button>
|
||||
))}
|
||||
{categories.length === 0 && (
|
||||
@ -219,7 +224,7 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
onClick={() => setSelectedProduct(product)}
|
||||
>
|
||||
<img
|
||||
src={product.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
src={product?.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
alt={product.name}
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
@ -247,7 +252,7 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center">
|
||||
{/* Category Filter */}
|
||||
<div className="relative">
|
||||
<select
|
||||
<select
|
||||
value={selectedCategorySlug}
|
||||
onChange={(e) => setSelectedCategorySlug(e.target.value)}
|
||||
className="appearance-none border border-[#1e4a6d]/20 bg-transparent py-2 pl-4 pr-10 text-[10px] font-bold uppercase tracking-widest outline-none transition-all focus:border-[#1e4a6d] cursor-pointer"
|
||||
@ -261,13 +266,13 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
<div className="h-1 w-1 rotate-45 border-b border-r border-[#1e4a6d]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Search Input */}
|
||||
<div className="relative flex items-center">
|
||||
<Search size={14} className="absolute left-3 opacity-40" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Cari produk..."
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Cari produk..."
|
||||
value={search}
|
||||
onChange={(e) => 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]"
|
||||
@ -288,7 +293,7 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
onClick={() => setSelectedProduct(item)}
|
||||
>
|
||||
<img
|
||||
src={item.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
src={item?.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
alt={item.name}
|
||||
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
|
||||
/>
|
||||
@ -305,8 +310,8 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
{item.name}
|
||||
</p>
|
||||
<p className="mb-4 text-sm font-medium opacity-60">{formatCurrency(item.retail_price)}</p>
|
||||
|
||||
<a
|
||||
|
||||
<a
|
||||
href={`https://wa.me/628123456789?text=${encodeURIComponent(`Halo VN Grup, saya ingin memesan ${item.name} seharga ${formatCurrency(item.retail_price)}. Mohon info detail pembayarannya.`)}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@ -324,7 +329,7 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
</div>
|
||||
<h3 className="mb-2 text-xl font-medium">Produk tidak ditemukan</h3>
|
||||
<p className="mb-8 text-sm opacity-60">Coba gunakan kata kunci lain atau periksa ejaan Anda.</p>
|
||||
<button
|
||||
<button
|
||||
onClick={() => {
|
||||
setSearch('');
|
||||
setSelectedCategorySlug('');
|
||||
@ -501,24 +506,47 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2">
|
||||
{/* Product Images */}
|
||||
<div className="border-b border-[#1e4a6d]/10 md:border-b-0 md:border-r overflow-hidden bg-white">
|
||||
<div className="aspect-[4/5] overflow-hidden">
|
||||
<div className="border-b border-[#1e4a6d]/10 md:border-b-0 md:border-r overflow-hidden bg-[#fdfcf9]">
|
||||
<div className="aspect-[4/5] overflow-hidden relative group/hero">
|
||||
<img
|
||||
src={selectedProduct?.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
src={activeModalImage || selectedProduct?.thumbnail_url || 'https://images.unsplash.com/photo-1719947348940-7aa339028cbc?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1yZWxhdGVkfDgzfHx8ZW58MHx8fHx8'}
|
||||
alt={selectedProduct?.name}
|
||||
className="h-full w-full object-cover"
|
||||
className="h-full w-full object-cover transition-transform duration-700 hover:scale-105"
|
||||
/>
|
||||
{/* Blueprint overlay decoration */}
|
||||
<div className="absolute top-4 left-4 text-[8px] font-mono opacity-20 pointer-events-none">DET_V.1.0</div>
|
||||
</div>
|
||||
{/* Image Gallery if exists */}
|
||||
{selectedProduct?.images_data?.length > 0 && (
|
||||
<div className="flex border-t border-[#1e4a6d]/10">
|
||||
{selectedProduct.images_data.map((img: any, i: number) => (
|
||||
<div key={i} className="aspect-square w-20 border-r border-[#1e4a6d]/10 overflow-hidden">
|
||||
<img src={img.url} alt="detail" className="h-full w-full object-cover opacity-60 hover:opacity-100 transition-opacity cursor-pointer" />
|
||||
|
||||
{/* Refined Image Gallery List */}
|
||||
<div className="p-4 border-t border-[#1e4a6d]/10">
|
||||
<p className="text-[8px] font-bold uppercase tracking-[0.2em] mb-3 opacity-40">Galeri Foto</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{/* Thumbnail (Main Image) */}
|
||||
<div
|
||||
onClick={() => setActiveModalImage(selectedProduct?.thumbnail_url)}
|
||||
className={`relative aspect-square w-14 cursor-pointer overflow-hidden transition-all duration-300 ${activeModalImage === selectedProduct?.thumbnail_url
|
||||
? 'ring-1 ring-[#1e4a6d] ring-offset-2'
|
||||
: 'opacity-40 hover:opacity-100'
|
||||
}`}
|
||||
>
|
||||
<img src={selectedProduct?.thumbnail_url} className="h-full w-full object-cover" alt="main" />
|
||||
</div>
|
||||
|
||||
{/* Additional Images */}
|
||||
{selectedProduct?.images_data?.map((img: any, i: number) => (
|
||||
<div
|
||||
key={i}
|
||||
onClick={() => setActiveModalImage(img.url)}
|
||||
className={`relative aspect-square w-14 cursor-pointer overflow-hidden transition-all duration-300 ${activeModalImage === img.url
|
||||
? 'ring-1 ring-[#1e4a6d] ring-offset-2'
|
||||
: 'opacity-40 hover:opacity-100'
|
||||
}`}
|
||||
>
|
||||
<img src={img.url} className="h-full w-full object-cover" alt={`view ${i + 1}`} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
@ -541,7 +569,7 @@ export default function Homepage({ categories = [], bestSellers, topSellingProdu
|
||||
</div>
|
||||
|
||||
<div className="mt-auto pt-8 border-t border-[#1e4a6d]/10">
|
||||
<a
|
||||
<a
|
||||
href={`https://wa.me/628123456789?text=${encodeURIComponent(`Halo VN Grup, saya tertarik dengan produk ${selectedProduct?.name} seharga ${formatCurrency(selectedProduct?.retail_price || 0)}. Bisa tanya-tanya dulu?`)}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user