dstpabuaran.com/resources/js/pages/welcome.tsx
Yoga Pangestu 7d21a1e6db feat: add cart context and functionality, update welcome page with new components and styles
- Implemented CartContext for managing cart state, including adding, removing, and updating items.
- Added CartDrawer component to display cart items.
- Updated AppHeader to include cart item count.
- Enhanced welcome page with new layout, improved product image handling, and updated call-to-action buttons.
- Refactored homepage data types to accommodate new features and removed unused properties.
2026-08-13 17:19:56 +07:00

653 lines
38 KiB
TypeScript

import ProductCard from '@/components/home/ProductCard';
import CartDrawer from '@/components/home/CartDrawer';
import ProductModal from '@/components/home/ProductModal';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useCart } from '@/contexts/cart-context';
import { formatRupiah } from '@/lib/rupiah';
import type { Category, HomepageData, Paginated, Product, ProductPrice } from '@/types/homepage';
import { Head, InfiniteScroll, Link, router } from '@inertiajs/react';
import {
ArrowRight,
Check,
ChevronRight,
Info,
LogIn,
Mail,
MapPin,
Phone,
Plus,
Search,
ShoppingBag,
Star,
} from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
type Props = {
appName: string;
aboutApp: string | null;
contactEmail: string | null;
contactPhone: string | null;
contactAddress: string | null;
instagramUrl: string | null;
facebookUrl: string | null;
tiktokUrl: string | null;
homepage: HomepageData;
categories: Category[];
products: Paginated<Product>;
filters: { search: string; category: string };
seo: { title: string; description: string; image: string; url: string };
};
export default function Welcome({
appName,
aboutApp,
contactEmail,
contactPhone,
contactAddress,
instagramUrl,
facebookUrl,
tiktokUrl,
homepage,
categories,
products,
filters,
}: Props) {
const [searchInput, setSearchInput] = useState(filters.search);
const [selectedCategory, setSelectedCategory] = useState(filters.category);
const [activeProduct, setActiveProduct] = useState<Product | null>(null);
const [activeSection, setActiveSection] = useState('hero');
const [cartOpen, setCartOpen] = useState(false);
const searchTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const { totalItems } = useCart();
useEffect(() => {
const sections = ['hero', 'catalog', 'gallery', 'order-guide', 'about', 'contact'];
const observers: IntersectionObserver[] = [];
sections.forEach((id) => {
const el = document.getElementById(id);
if (!el) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setActiveSection(id);
}
},
{ rootMargin: '-40% 0px -55% 0px' },
);
observer.observe(el);
observers.push(observer);
});
return () => observers.forEach((o) => o.disconnect());
}, []);
const FALLBACK_IMAGE = 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=800&auto=format&fit=crop&q=80';
const getProductImage = (product: Product): string => {
for (const variant of product.product_variants) {
if (variant.photo_urls && variant.photo_urls.length > 0) {
return variant.photo_urls[0];
}
}
return FALLBACK_IMAGE;
};
const getProductPriceRange = (product: Product): string => {
const prices = product.product_variants.flatMap((v) =>
v.product_prices
.filter((p: ProductPrice) => p.type === 'retail')
.map((p: ProductPrice) => p.price),
);
if (prices.length === 0) {
const fallbackPrices = product.product_variants.flatMap((v) =>
v.product_prices.map((p: ProductPrice) => p.price),
);
if (fallbackPrices.length === 0) return 'Rp 0';
const min = Math.min(...fallbackPrices);
const max = Math.max(...fallbackPrices);
return min === max ? `Rp ${formatRupiah(min)}` : `Rp ${formatRupiah(min)} - Rp ${formatRupiah(max)}`;
}
const min = Math.min(...prices);
const max = Math.max(...prices);
return min === max ? `Rp ${formatRupiah(min)}` : `Rp ${formatRupiah(min)} - Rp ${formatRupiah(max)}`;
};
const fetchProducts = useCallback(
(search: string, category: string) => {
const params = new URLSearchParams();
if (search) params.set('search', search);
if (category) params.set('category', category);
const url = `/${params.toString() ? `?${params.toString()}` : ''}`;
router.visit(url, {
only: ['products', 'filters'],
reset: ['products'],
preserveState: true,
preserveScroll: true,
});
},
[],
);
const handleSearchChange = useCallback(
(value: string) => {
setSearchInput(value);
if (searchTimeoutRef.current) {
clearTimeout(searchTimeoutRef.current);
}
searchTimeoutRef.current = setTimeout(() => {
fetchProducts(value, selectedCategory);
}, 400);
},
[selectedCategory, fetchProducts],
);
const handleCategoryChange = useCallback(
(slug: string | null) => {
const newCategory = slug ?? '';
setSelectedCategory(newCategory);
fetchProducts(searchInput, newCategory);
},
[searchInput, fetchProducts],
);
const handleResetFilters = useCallback(() => {
setSearchInput('');
setSelectedCategory('');
fetchProducts('', '');
}, [fetchProducts]);
const featuredProducts = products.data.slice(0, 3);
return (
<>
<Head title={appName}>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
</Head>
<div className="min-h-screen bg-gradient-to-tr from-amber-50/20 via-[#FDFDFC] to-yellow-50/30 text-slate-800 transition-colors duration-300 font-sans scroll-smooth">
{/* Sticky Header */}
<header className="sticky top-0 z-40 bg-white/70 backdrop-blur-lg border-b border-amber-100/50 transition-all">
<div className="max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
<Link href="/" className="flex items-center">
<img src="/assets/logo.png" alt={appName} className="h-12 w-auto" />
</Link>
<nav className="hidden lg:flex items-center space-x-8 text-xs font-semibold uppercase tracking-widest text-slate-600">
{[
{ id: 'hero', label: 'Beranda' },
{ id: 'catalog', label: 'Produk' },
{ id: 'about', label: 'Tentang Kami' },
{ id: 'order-guide', label: 'Cara Pesan' },
{ id: 'contact', label: 'Hubungi Kami' },
].map((item) => (
<a
key={item.id}
href={`#${item.id}`}
className={`transition-colors ${activeSection === item.id ? 'text-amber-600' : 'hover:text-amber-600'}`}
>
{item.label}
</a>
))}
</nav>
<div className="flex items-center gap-2">
<Button variant="ghost" size="icon" onClick={() => setCartOpen(true)} className="relative">
<ShoppingBag className="w-4.5 h-4.5 text-amber-600" />
{totalItems > 0 && (
<span className="absolute -top-1 -right-1 w-4.5 h-4.5 bg-amber-600 text-white text-[9px] font-bold rounded-full flex items-center justify-center">
{totalItems}
</span>
)}
</Button>
<Button variant="ghost" size="icon" asChild>
<a href="/admin/dashboard" aria-label="Login">
<LogIn className="w-4.5 h-4.5 text-amber-600" />
</a>
</Button>
</div>
</div>
</header>
{/* Hero Section */}
<section id="hero" className="relative min-h-[calc(100vh-80px)] flex flex-col justify-between overflow-hidden">
<div className="absolute inset-0 grid grid-cols-1 lg:grid-cols-2 pointer-events-none z-0">
<div className="bg-white/40/30" />
<div className="bg-gradient-to-tr from-amber-100/30 via-yellow-100/20 to-orange-50/30 border-l border-amber-100/20" />
</div>
<div className="max-w-7xl mx-auto px-6 w-full lg:grow grid grid-cols-1 lg:grid-cols-12 gap-8 items-center py-12 z-10">
{/* Left Column */}
<div className="lg:col-span-5 flex flex-col justify-center space-y-6 lg:pr-6">
<Badge variant="secondary" className="w-fit bg-amber-500/10 text-amber-700 uppercase tracking-widest font-bold px-3 py-1 shadow-sm">
Hadir dengan Gaya Terbaru
</Badge>
<h1 className="text-5xl md:text-6xl font-serif leading-[1.1] tracking-tight font-light select-none text-slate-800">
Nyaman<br />
dalam setiap{' '}
<span className="font-normal italic text-amber-600 bg-amber-100/20 px-2 rounded-lg">
Penampilan
</span>
</h1>
<p className="text-sm text-slate-500 max-w-md leading-relaxed font-light">
Koleksi fashion wanita dengan sentuhan elegan, material berkualitas, dan kenyamanan yang dapat Anda rasakan di setiap pemakaian.
</p>
<div className="flex items-center space-x-4 pt-4">
<Button asChild className="bg-amber-600 text-white px-8 py-3.5 text-xs font-semibold uppercase tracking-widest rounded-xl shadow-lg shadow-amber-200/50 hover:bg-amber-500 hover:-translate-y-0.5 transition-all duration-300 group">
<a href="#catalog">
Beli Sekarang
<ArrowRight className="w-3.5 h-3.5 ml-2 transform group-hover:translate-x-1 transition-transform" />
</a>
</Button>
<Button variant="outline" asChild className="border-amber-200 text-xs font-semibold uppercase tracking-widest px-8 py-3.5 rounded-xl hover:bg-amber-500/5 hover:border-amber-400 transition-all">
<a href="#about">Tentang Kami</a>
</Button>
</div>
</div>
{/* Center Column: Visual */}
<div className="lg:col-span-7 relative flex justify-center items-center h-[500px] lg:h-[650px] w-full">
<div className="absolute inset-0 -z-10 flex justify-center items-center pointer-events-none select-none">
<div className="absolute w-[350px] h-[350px] rounded-full bg-gradient-to-tr from-amber-400/25 via-yellow-400/20 to-orange-300/20 blur-3xl" />
<div className="absolute w-[400px] h-[400px] rounded-full bg-gradient-to-br from-rose-300/20 via-amber-200/20 to-orange-300/20 blur-3xl" />
</div>
<div className="absolute inset-0 flex justify-center items-center pointer-events-none select-none z-0">
<div className="text-[14vw] lg:text-[120px] font-serif font-bold leading-none tracking-tight flex text-amber-200">
<span className="text-amber-600">DST</span>
<span className="text-slate-900">Collection</span>
</div>
</div>
<div className="relative w-[310px] h-[440px] lg:w-[390px] lg:h-[540px] rounded-[2rem] overflow-hidden z-10 transition-transform duration-500 hover:scale-[1.02]">
<img
src={homepage.hero_image_url || 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=1000&auto=format&fit=crop&q=80'}
alt={appName}
className="w-full h-full object-cover"
/>
</div>
{/* Floating Tag 1 */}
{featuredProducts[0] && (
<div
onClick={() => setActiveProduct(featuredProducts[0])}
className="absolute top-10 left-4 md:-left-6 z-20 flex items-center space-x-3 bg-white/90 backdrop-blur-md p-3 rounded-2xl shadow-lg border border-amber-100/40 cursor-pointer transform hover:-translate-y-1 transition-all"
>
<img
src={getProductImage(featuredProducts[0])}
alt="Preview Produk"
className="w-10 h-10 object-cover rounded-lg"
/>
<div className="text-left">
<h4 className="text-[9px] font-bold text-amber-600 uppercase tracking-widest">Terpopuler</h4>
<p className="text-[11px] font-semibold truncate max-w-[100px]">{featuredProducts[0].name}</p>
<span className="text-[11px] font-bold text-amber-600">{getProductPriceRange(featuredProducts[0])}</span>
</div>
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-amber-50/50 text-amber-600">
<Plus className="w-3.5 h-3.5" />
</div>
</div>
)}
{/* Floating Tag 2 */}
{featuredProducts[1] && (
<div
onClick={() => setActiveProduct(featuredProducts[1])}
className="absolute top-28 right-4 md:-right-6 z-20 flex items-center space-x-3 bg-white/90 backdrop-blur-md p-3 rounded-2xl shadow-lg border border-amber-100/40 cursor-pointer transform hover:-translate-y-1 transition-all"
>
<img
src={getProductImage(featuredProducts[1])}
alt="Preview Produk"
className="w-10 h-10 object-cover rounded-lg"
/>
<div className="text-left">
<div className="flex items-center text-amber-400 space-x-0.5 mb-0.5">
{[1, 2, 3, 4, 5].map((i) => (
<Star key={i} className="w-2.5 h-2.5 fill-current" />
))}
</div>
<p className="text-[11px] font-semibold truncate max-w-[100px]">{featuredProducts[1].name}</p>
<span className="text-[10px] font-semibold text-emerald-500">Stok Tersedia</span>
</div>
</div>
)}
</div>
</div>
{/* Scroll Indicator */}
<div className="max-w-7xl mx-auto px-6 w-full flex items-center justify-between pb-8 z-10 text-xs font-semibold text-slate-500">
<div className="flex items-center space-x-3">
<span className="text-amber-600">#DSTCollection</span>
<span className="w-1 h-1 rounded-full bg-amber-300" />
<span>Bahan Adem & Lembut</span>
</div>
<Button
variant="ghost"
onClick={() => {
document.getElementById('catalog')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}}
className="flex items-center space-x-2 hover:text-amber-600 transition-colors cursor-pointer text-xs font-semibold uppercase tracking-widest text-slate-500"
>
<span>Lihat katalog lengkap</span>
<ChevronRight className="w-3.5 h-3.5 rotate-90 text-amber-600" />
</Button>
</div>
</section>
{/* Catalog Section */}
<section id="catalog" className="max-w-7xl mx-auto px-6 py-20 border-t border-amber-100/30">
<div className="space-y-6 mb-12">
<div className="text-center space-y-2">
<Badge variant="secondary" className="bg-amber-500/10 text-amber-700 uppercase tracking-[0.3em] font-bold px-3 py-1">
Katalog Eksklusif
</Badge>
<h3 className="text-3xl font-serif text-slate-800">Koleksi Busana Pilihan</h3>
<p className="text-sm text-slate-500 max-w-lg mx-auto font-light">Gunakan kategori dan filter di bawah untuk menyesuaikan pencarian busana idaman Anda dengan mudah.</p>
</div>
{/* Filters */}
<div className="bg-white/80 backdrop-blur-md p-6 rounded-3xl shadow-sm border border-amber-100/30 flex flex-col md:flex-row items-center gap-4 justify-between">
<div className="relative w-full md:w-80">
<Input
value={searchInput}
onChange={(e) => handleSearchChange(e.target.value)}
type="text"
placeholder="Cari produk..."
className="w-full bg-slate-50 border-slate-200 text-xs px-4 py-3 pr-10 rounded-xl focus:border-amber-500 text-slate-700 transition-all"
/>
<Search className="absolute right-3 top-3.5 w-4 h-4 text-slate-400" />
</div>
<div className="flex flex-wrap gap-2 w-full md:w-auto">
<Button
variant={!selectedCategory ? 'default' : 'outline'}
size="sm"
onClick={() => handleCategoryChange(null)}
className={`shrink-0 text-[11px] font-semibold uppercase tracking-wider rounded-xl transition-all whitespace-nowrap ${!selectedCategory
? 'bg-amber-600 text-white border-transparent shadow-md shadow-amber-200/50'
: 'bg-transparent text-slate-600 border-slate-200 hover'
}`}
>
Semua
</Button>
{categories.map((category) => (
<Button
key={category.id}
variant={selectedCategory === category.slug ? 'default' : 'outline'}
size="sm"
onClick={() => handleCategoryChange(selectedCategory === category.slug ? null : category.slug)}
className={`shrink-0 text-[11px] font-semibold uppercase tracking-wider rounded-xl transition-all whitespace-nowrap ${selectedCategory === category.slug
? 'bg-amber-600 text-white border-transparent shadow-md shadow-amber-200/50'
: 'bg-transparent text-slate-600 border-slate-200 hover'
}`}
>
{category.name}
</Button>
))}
</div>
</div>
</div>
{/* Product Grid with Infinite Scroll */}
<InfiniteScroll
data="products"
onlyNext
buffer={300}
loading={() => (
<div className="col-span-full flex justify-center py-8">
<div className="flex items-center space-x-3 text-sm text-slate-400">
<div className="w-5 h-5 border-2 border-amber-400 border-t-transparent animate-spin rounded-full" />
<span>Memuat produk lainnya...</span>
</div>
</div>
)}
>
{products.data.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-x-8 gap-y-12">
{products.data.map((product) => (
<ProductCard
key={product.id}
product={product}
onQuickView={setActiveProduct}
contactPhone={contactPhone}
/>
))}
</div>
) : (
<div className="text-center py-20 space-y-3">
<Info className="w-12 h-12 text-amber-300 mx-auto" />
<h3 className="text-lg font-medium text-slate-700">Produk Tidak Ditemukan</h3>
<p className="text-sm text-slate-400">
Mohon maaf, kami tidak menemukan pakaian yang cocok dengan kata kunci pencarian Anda.
</p>
<Button variant="ghost" onClick={handleResetFilters} className="mt-2 text-xs font-bold uppercase tracking-widest text-amber-600 underline underline-offset-4">
Reset Pencarian
</Button>
</div>
)}
</InfiniteScroll>
</section>
{/* Gallery Section */}
<section id="gallery" className="w-full bg-gradient-to-br from-amber-50/40 via-yellow-50/20 to-orange-50/30 py-24 border-t border-b border-amber-100/30">
<div className="max-w-7xl mx-auto px-6 space-y-12">
<div className="text-center space-y-3 max-w-lg mx-auto">
<Badge variant="secondary" className="bg-amber-500/10 text-amber-700 uppercase tracking-[0.3em] font-bold px-3 py-1">
Galeri Kami
</Badge>
<h3 className="text-4xl font-serif leading-tight">Koleksi Lookbook</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light">Intip koleksi lookbook kami untuk inspirasi gaya sehari-hari. Padu padan pakaian modern yang nyaman untuk berbagai suasana.</p>
</div>
{homepage.gallery_images.length > 0 ? (
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{homepage.gallery_images.map((image, index) => (
<div
key={index}
className="group relative aspect-[3/4] rounded-2xl overflow-hidden shadow-md border-2 border-white cursor-pointer transition-all duration-300 hover:shadow-xl hover:-translate-y-1"
>
<img
src={image}
alt={`Lookbook ${index + 1}`}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-gradient-to-t from-amber-950/40 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
</div>
))}
</div>
) : (
<div className="text-center py-12">
<p className="text-sm text-slate-400">Belum ada foto lookbook yang ditambahkan.</p>
</div>
)}
</div>
</section>
{/* Order Guide Section */}
<section id="order-guide" className="max-w-7xl mx-auto px-6 py-20 border-b border-amber-100/30">
<div className="text-center space-y-3 mb-16">
<Badge variant="secondary" className="bg-amber-500/10 text-amber-700 uppercase tracking-[0.3em] font-bold px-3 py-1">
Langkah Pemesanan
</Badge>
<h4 className="text-3xl font-serif">Cara Melakukan Pemesanan</h4>
<p className="text-sm text-slate-500 max-w-md mx-auto font-light">Sistem pemesanan kami sangat mudah dan terhubung langsung via WhatsApp untuk pelayanan cepat dan personal.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{[
{ title: 'Pilih Produk', description: 'Jelajahi pakaian favorit Anda, lalu ketuk "Lihat Detail" untuk memeriksa varian.' },
{ title: 'Pilih Varian & Harga', description: 'Tentukan varian yang diinginkan dan pilih jenis harga (Eceran, Grosir, Agen, dll.).' },
{ title: 'Masukkan Keranjang', description: 'Masukkan ke Keranjang Belanja untuk menampung seluruh daftar pakaian yang ingin Anda beli.' },
{ title: 'Kirim ke WhatsApp', description: 'Klik tombol kirim pesanan, admin kami akan merespons rincian transfer bank dan pengiriman kurir.' },
].map((step, index) => (
<div
key={index}
className="bg-white/50 p-6 rounded-2xl border border-amber-100/30 shadow-sm relative overflow-hidden text-center group hover:-translate-y-1 transition-transform"
>
<div className="absolute -top-4 -right-4 w-16 h-16 bg-amber-100/50 rounded-full flex items-center justify-center text-amber-600 font-bold text-xl font-serif">
{index + 1}
</div>
<div className="w-12 h-12 rounded-xl bg-amber-100/30 text-amber-600 flex items-center justify-center mx-auto mb-4">
{index === 0 && <ShoppingBag className="w-5 h-5" />}
{index === 1 && <Star className="w-5 h-5" />}
{index === 2 && <Plus className="w-5 h-5" />}
{index === 3 && <Phone className="w-5 h-5" />}
</div>
<h5 className="font-bold text-base mb-2">{step.title}</h5>
<p className="text-xs text-slate-400 leading-relaxed font-light">{step.description}</p>
</div>
))}
</div>
</section>
{/* About Section */}
<section id="about" className="max-w-7xl mx-auto px-6 py-20 border-b border-amber-100/30">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
<div className="lg:col-span-6 relative aspect-square max-w-md mx-auto lg:max-w-none rounded-3xl overflow-hidden shadow-lg border-2 border-white">
<img
src={homepage.about_image_url || 'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80'}
alt="Tentang Kami"
className="w-full h-full object-cover"
/>
</div>
<div className="lg:col-span-6 space-y-6">
<Badge variant="secondary" className="bg-amber-500/10 text-amber-700 uppercase tracking-[0.3em] font-bold px-3 py-1">
Tentang Kami
</Badge>
<h3 className="text-3xl font-serif">DST Collection</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light whitespace-pre-line">
{aboutApp || 'Kami adalah rumah produksi busana lokal berkualitas tinggi. Berfokus pada keindahan motif, ketepatan detail jahitan, dan pemilihan kain adem yang mengedepankan aspek fungsionalitas dan estetika.'}
</p>
{['Kain Rayon Super Tebal & Menyerap Keringat', 'Motif Eksklusif & Tidak Pasaran', 'Dukungan Penuh Layanan Admin Via WhatsApp'].map((feature, index) => (
<div key={index} className="flex items-center space-x-3 text-xs text-slate-500 font-semibold">
<Check className="w-4 h-4 text-emerald-500" />
<span>{feature}</span>
</div>
))}
</div>
</div>
</section>
{/* Contact Section */}
<section id="contact" className="max-w-7xl mx-auto px-6 py-20">
<div className="bg-white/60 backdrop-blur-md border border-amber-100/30 rounded-3xl overflow-hidden shadow-sm grid grid-cols-1 lg:grid-cols-2">
<div className="p-8 space-y-6 flex flex-col justify-center">
<Badge variant="secondary" className="bg-amber-500/10 text-amber-700 uppercase tracking-[0.3em] font-bold px-3 py-1 w-fit">
Kontak Kami
</Badge>
<h3 className="text-3xl font-serif">Ada Pertanyaan? Hubungi Kami</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light">Kami sangat senang mendengarkan pertanyaan Anda terkait spesifikasi produk, ketersediaan grosir, atau kemitraan. Hubungi tim admin kami melalui media di bawah.</p>
<div className="space-y-3">
{contactPhone && (
<div className="flex items-center space-x-3 text-sm">
<div className="w-8 h-8 rounded-lg bg-amber-100/40 text-amber-600 flex items-center justify-center">
<Phone className="w-4 h-4" />
</div>
<span>{contactPhone}</span>
</div>
)}
{contactEmail && (
<div className="flex items-center space-x-3 text-sm">
<div className="w-8 h-8 rounded-lg bg-amber-100/40 text-amber-600 flex items-center justify-center">
<Mail className="w-4 h-4" />
</div>
<span>{contactEmail}</span>
</div>
)}
{contactAddress && (
<div className="flex items-center space-x-3 text-sm">
<div className="w-8 h-8 rounded-lg bg-amber-100/40 text-amber-600 flex items-center justify-center">
<MapPin className="w-4 h-4" />
</div>
<span>{contactAddress}</span>
</div>
)}
</div>
</div>
<div className="h-80 lg:h-auto">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d304.913429094586!2d107.58352379265978!3d-6.414270414938328!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2e696bd874fdab6d%3A0x12de5546c3d8eac4!2sAGEN%20JNE%20DEESTEPABUARAN!5e1!3m2!1sen!2sid!4v1786611903455!5m2!1sen!2sid"
width="100%"
height="100%"
style={{ border: 0 }}
allowFullScreen
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
className="w-full h-full min-h-[320px]"
/>
</div>
</div>
</section>
{/* Footer */}
<footer className="bg-white text-slate-600 py-16 border-t border-amber-100/30">
<div className="max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="space-y-4">
<img src="/assets/logo.png" alt={appName} className="h-10 w-auto" />
<p className="text-xs text-slate-400 leading-relaxed font-light">
Galeri resmi {appName}. Pilihan busana lokal premium berpotongan modern dengan kenyamanan menyejukkan.
</p>
</div>
<div className="space-y-3">
<h4 className="text-xs uppercase font-bold text-slate-800 tracking-widest">Koleksi Kami</h4>
<ul className="space-y-2 text-xs">
{categories.slice(0, 4).map((cat) => (
<li key={cat.id}>
<a href="#catalog" className="hover transition-colors">{cat.name}</a>
</li>
))}
</ul>
</div>
<div className="space-y-3">
<h4 className="text-xs uppercase font-bold text-slate-800 tracking-widest">Tautan</h4>
<ul className="space-y-2 text-xs">
<li><a href="#about" className="hover transition-colors">Tentang Kami</a></li>
<li><a href="#order-guide" className="hover transition-colors">Cara Pemesanan</a></li>
<li><a href="#contact" className="hover transition-colors">Hubungi Kami</a></li>
<li><a href="/admin/dashboard" className="hover transition-colors font-semibold">Login Dashboard Admin</a></li>
</ul>
</div>
<div className="space-y-3">
<h4 className="text-xs uppercase font-bold text-slate-800 tracking-widest">Sosial Media</h4>
<p className="text-xs text-slate-400 font-light">Ikuti sosial media kami untuk mendapatkan update produk terbaru.</p>
<div className="flex space-x-3 text-xs">
{instagramUrl && (
<a href={instagramUrl} target="_blank" rel="noreferrer" className="text-slate-400 hover">Instagram</a>
)}
{facebookUrl && (
<a href={facebookUrl} target="_blank" rel="noreferrer" className="text-slate-400 hover">Facebook</a>
)}
{tiktokUrl && (
<a href={tiktokUrl} target="_blank" rel="noreferrer" className="text-slate-400 hover">TikTok</a>
)}
</div>
</div>
</div>
<div className="max-w-7xl mx-auto px-6 mt-12 pt-8 border-t border-amber-100/30 flex flex-col sm:flex-row justify-between items-center text-[10px] text-slate-400 font-light space-y-4 sm:space-y-0">
<p>&copy; {new Date().getFullYear()} {appName}. Hak Cipta Dilindungi.</p>
</div>
</footer>
{/* Product Modal */}
<ProductModal product={activeProduct} onClose={() => setActiveProduct(null)} contactPhone={contactPhone} />
<CartDrawer open={cartOpen} onClose={() => setCartOpen(false)} contactPhone={contactPhone} />
</div>
</>
);
}