dstpabuaran.com/resources/js/pages/welcome.tsx
Yoga Pangestu 4733df5827 Add homepage types and update routing to use HomepageController
- Created a new TypeScript file for homepage-related types including Product, ProductVariant, ProductCategory, and HomepageData.
- Updated the index.ts to export the new homepage types.
- Refactored the web routes to replace the inline closure for the home route with the HomepageController.
2026-08-07 17:29:59 +07:00

623 lines
36 KiB
TypeScript

import { Head, Link, router, InfiniteScroll } from '@inertiajs/react';
import { useState, useCallback, useRef } from 'react';
import {
Search,
ShoppingBag,
Plus,
ArrowRight,
Star,
Info,
ChevronRight,
Phone,
MapPin,
Mail,
LogIn,
Check,
} from 'lucide-react';
import { formatRupiah } from '@/lib/rupiah';
import ProductCard from '@/components/home/ProductCard';
import ProductModal from '@/components/home/ProductModal';
import type { Product, Category, HomepageData, ProductPrice, Paginated } from '@/types/homepage';
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 searchTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);
const getProductImage = (product: Product): string => {
const fallbacks: Record<string, string[]> = {
daster: [
'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80',
],
'setelan-celana': [
'https://images.unsplash.com/photo-1539109136881-3be0616acf4b?w=800&auto=format&fit=crop&q=80',
],
atasan: [
'https://images.unsplash.com/photo-1515886657613-9f3515b0c78f?w=800&auto=format&fit=crop&q=80',
],
bawahan: [
'https://images.unsplash.com/photo-1583496661160-fb4886b36ca7?w=800&auto=format&fit=crop&q=80',
],
};
const firstCat = product.categories?.[0]?.slug || '';
const urls = fallbacks[firstCat] || [
'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=800&auto=format&fit=crop&q=80',
];
return urls[0];
};
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]);
// Use first 3 products from current page as featured for hero
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">
<div className="flex items-center space-x-3">
<Link href="/" className="flex items-center space-x-2">
<span className="font-serif text-2xl font-bold tracking-widest text-amber-600">
{appName}
</span>
</Link>
</div>
<nav className="hidden lg:flex items-center space-x-8 text-xs font-semibold uppercase tracking-widest text-slate-600">
<a href="#" className="hover:text-amber-600 transition-colors">Beranda</a>
<a href="#catalog" className="hover:text-amber-600 transition-colors">Produk</a>
<a href="#about" className="hover:text-amber-600 transition-colors">Tentang Kami</a>
<a href="#order-guide" className="hover:text-amber-600 transition-colors">Cara Pesan</a>
<a href="#contact" className="hover:text-amber-600 transition-colors">Hubungi Kami</a>
</nav>
<div className="flex items-center space-x-4">
<a
href="/admin/dashboard"
className="p-2 rounded-full hover:bg-amber-50 text-slate-600 transition-colors"
aria-label="Login"
>
<LogIn className="w-4.5 h-4.5 text-amber-600" />
</a>
</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">
<div className="inline-flex items-center space-x-2 bg-amber-500/10/10 text-[10px] text-amber-700 uppercase tracking-widest px-3 py-1 rounded-full w-fit font-bold shadow-sm">
<span>{homepage.hero_badge}</span>
</div>
<h1 className="text-5xl md:text-6xl font-serif leading-[1.1] tracking-tight font-light select-none text-slate-800">
{homepage.hero_title_line1} <br />
{homepage.hero_title_line2}{' '}
<span className="font-normal italic text-amber-600 bg-amber-100/20 px-2 rounded-lg">
{homepage.hero_title_highlight}
</span>
</h1>
<p className="text-sm text-slate-500 max-w-md leading-relaxed font-light">
{homepage.hero_description}
</p>
<div className="flex items-center space-x-4 pt-4">
<a
href="#catalog"
className="inline-flex items-center justify-center 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"
>
{homepage.hero_cta_primary_text}
<ArrowRight className="w-3.5 h-3.5 ml-2 transform group-hover:translate-x-1 transition-transform" />
</a>
<a
href="#about"
className="inline-flex items-center justify-center border 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"
>
{homepage.hero_cta_secondary_text}
</a>
</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 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 opacity-[0.03]">
<span className="text-slate-900">{homepage.hero_bg_text_left}</span>
<span className="text-amber-600">{homepage.hero_bg_text_right}</span>
</div>
</div>
<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="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">#{homepage.scroll_hashtag}</span>
<span className="w-1 h-1 rounded-full bg-amber-300" />
<span>{homepage.scroll_tagline}</span>
</div>
<a href="#catalog" className="flex items-center space-x-2 hover:text-amber-600 transition-colors">
<span>Lihat katalog lengkap</span>
<ChevronRight className="w-3.5 h-3.5 rotate-90 text-amber-600" />
</a>
</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">
<h2 className="text-xs uppercase tracking-[0.3em] font-bold text-amber-600">{homepage.catalog_badge}</h2>
<h3 className="text-3xl font-serif text-slate-800">{homepage.catalog_title}</h3>
<p className="text-sm text-slate-500 max-w-lg mx-auto font-light">{homepage.catalog_description}</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={homepage.catalog_search_placeholder}
className="w-full bg-slate-50 border border-slate-200 text-xs px-4 py-3 pr-10 rounded-xl outline-none 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
onClick={() => handleCategoryChange(null)}
className={`shrink-0 px-4 py-2 text-[11px] font-semibold uppercase tracking-wider rounded-xl border 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}
onClick={() => handleCategoryChange(selectedCategory === category.slug ? null : category.slug)}
className={`shrink-0 px-4 py-2 text-[11px] font-semibold uppercase tracking-wider rounded-xl border 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}
/>
))}
</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
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">
<span className="text-xs uppercase tracking-[0.3em] font-bold text-amber-600">{homepage.gallery_badge}</span>
<h3 className="text-4xl font-serif leading-tight">{homepage.gallery_title}</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light">{homepage.gallery_description}</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">
<h3 className="text-xs uppercase tracking-[0.3em] font-bold text-amber-600">{homepage.order_guide_badge}</h3>
<h4 className="text-3xl font-serif">{homepage.order_guide_title}</h4>
<p className="text-sm text-slate-500 max-w-md mx-auto font-light">{homepage.order_guide_description}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{homepage.order_steps.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">
<span className="text-xs uppercase tracking-[0.3em] font-bold text-amber-600">{homepage.about_badge}</span>
<h3 className="text-3xl font-serif">{homepage.about_title}</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light whitespace-pre-line">
{aboutApp || 'Kami adalah rumah produksi busana dan batik lokal berkualitas tinggi. Berfokus pada keindahan motif, ketepatan detail jahitan, dan pemilihan kain adem yang mengedepankan aspek fungsionalitas dan estetika.'}
</p>
{homepage.about_features.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 p-8 rounded-3xl grid grid-cols-1 lg:grid-cols-2 gap-12 items-center shadow-sm">
<div className="space-y-6">
<span className="text-xs uppercase tracking-[0.3em] font-bold text-amber-600">{homepage.contact_badge}</span>
<h3 className="text-3xl font-serif">{homepage.contact_title}</h3>
<p className="text-sm text-slate-500 leading-relaxed font-light">{homepage.contact_description}</p>
<div className="space-y-4">
{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="bg-slate-50 p-6 rounded-2xl border border-slate-200 space-y-4">
<h4 className="font-bold text-base">{homepage.contact_form_title}</h4>
<div className="space-y-3">
<input
type="text"
placeholder="Nama Anda"
className="w-full text-xs px-4 py-3 bg-white border border-slate-200 rounded-lg outline-none focus:border-amber-500 text-slate-700"
/>
<textarea
placeholder="Tulis pesan Anda di sini..."
rows={4}
className="w-full text-xs px-4 py-3 bg-white border border-slate-200 rounded-lg outline-none focus:border-amber-500 text-slate-700"
/>
<a
href={`https://wa.me/${(contactPhone || '6281234567890').replace(/[^0-9]/g, '')}`}
target="_blank"
rel="noreferrer"
className="w-full inline-flex items-center justify-center bg-emerald-600 hover:bg-emerald-500 text-white py-3 rounded-lg text-xs font-bold uppercase tracking-wider transition-colors"
>
<Phone className="w-4 h-4 mr-2" />
Kirim Melalui WhatsApp
</a>
</div>
</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">
<div className="flex items-center space-x-2">
<span className="font-serif text-xl font-bold tracking-widest text-amber-600">
{appName}
</span>
</div>
<p className="text-xs text-slate-400 leading-relaxed font-light">
{homepage.footer_description}
</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}. {homepage.footer_copyright}</p>
</div>
</footer>
{/* Product Modal */}
<ProductModal product={activeProduct} onClose={() => setActiveProduct(null)} />
</div>
</>
);
}