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.
This commit is contained in:
Yoga Pangestu 2026-08-07 17:29:59 +07:00
parent 3c945a1372
commit 4733df5827
7 changed files with 1174 additions and 380 deletions

View File

@ -0,0 +1,127 @@
<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Product;
use App\Services\S3PresignedService;
use App\Settings\HomepageSettings;
use App\Settings\SocialMediaSettings;
use App\Settings\SystemSettings;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class HomepageController extends Controller
{
public function __construct(
private S3PresignedService $s3Service,
) {}
public function __invoke(Request $request): Response
{
$system = app(SystemSettings::class);
$homepage = app(HomepageSettings::class);
$socialMedia = app(SocialMediaSettings::class);
$categories = Category::select(['id', 'name', 'slug'])
->orderBy('name')
->get();
$search = $request->input('search', '');
$category = $request->input('category', '');
$productsQuery = Product::select(['id', 'name', 'slug', 'description', 'status'])
->active()
->with([
'categories:id,name,slug',
'productVariants:id,product_id,name,stock',
'productVariants.productPrices:id,variant_id,type,price',
]);
if ($search !== '') {
$productsQuery->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
if ($category !== '') {
$productsQuery->whereHas('categories', function ($q) use ($category) {
$q->where('slug', $category);
});
}
$products = Inertia::scroll(
fn () => $productsQuery->orderBy('created_at', 'desc')->paginate(12)
);
$galleryImages = array_map(
fn ($key) => str_starts_with($key, 'http') ? $key : $this->s3Service->getTemporaryUrl($key, 60),
$homepage->gallery_images ?? [],
);
return Inertia::render('welcome', [
'appName' => $system->app_name,
'aboutApp' => $system->about_app,
'contactEmail' => $system->email,
'contactPhone' => $system->phone,
'contactAddress' => $system->address,
'instagramUrl' => $socialMedia->instagram_url,
'facebookUrl' => $socialMedia->facebook_url,
'tiktokUrl' => $socialMedia->tiktok_url,
'homepage' => [
'hero_badge' => $homepage->hero_badge,
'hero_title_line1' => $homepage->hero_title_line1,
'hero_title_line2' => $homepage->hero_title_line2,
'hero_title_highlight' => $homepage->hero_title_highlight,
'hero_description' => $homepage->hero_description,
'hero_cta_primary_text' => $homepage->hero_cta_primary_text,
'hero_cta_secondary_text' => $homepage->hero_cta_secondary_text,
'hero_image_url' => $homepage->hero_image_url
? (str_starts_with($homepage->hero_image_url, 'http') ? $homepage->hero_image_url : $this->s3Service->getTemporaryUrl($homepage->hero_image_url, 60))
: null,
'hero_bg_text_left' => $homepage->hero_bg_text_left,
'hero_bg_text_right' => $homepage->hero_bg_text_right,
'scroll_hashtag' => $homepage->scroll_hashtag,
'scroll_tagline' => $homepage->scroll_tagline,
'catalog_badge' => $homepage->catalog_badge,
'catalog_title' => $homepage->catalog_title,
'catalog_description' => $homepage->catalog_description,
'catalog_search_placeholder' => $homepage->catalog_search_placeholder,
'gallery_badge' => $homepage->gallery_badge,
'gallery_title' => $homepage->gallery_title,
'gallery_description' => $homepage->gallery_description,
'gallery_images' => $galleryImages,
'order_guide_badge' => $homepage->order_guide_badge,
'order_guide_title' => $homepage->order_guide_title,
'order_guide_description' => $homepage->order_guide_description,
'order_steps' => $homepage->order_steps,
'about_badge' => $homepage->about_badge,
'about_title' => $homepage->about_title,
'about_image_url' => $homepage->about_image_url
? (str_starts_with($homepage->about_image_url, 'http') ? $homepage->about_image_url : $this->s3Service->getTemporaryUrl($homepage->about_image_url, 60))
: null,
'about_features' => $homepage->about_features,
'contact_badge' => $homepage->contact_badge,
'contact_title' => $homepage->contact_title,
'contact_description' => $homepage->contact_description,
'contact_form_title' => $homepage->contact_form_title,
'footer_description' => $homepage->footer_description,
'footer_copyright' => $homepage->footer_copyright,
],
'categories' => $categories,
'products' => $products,
'filters' => [
'search' => $search,
'category' => $category,
],
'seo' => [
'title' => $system->app_name . ' - ' . $homepage->hero_badge,
'description' => $homepage->hero_description,
'image' => url('/assets/logo.png'),
'url' => url('/'),
],
]);
}
}

View File

@ -0,0 +1,117 @@
import { formatRupiah } from '@/lib/rupiah';
import type { Product } from '@/types/homepage';
type ProductCardProps = {
product: Product;
onQuickView: (product: Product) => void;
};
function getProductImage(product: Product): string {
for (const variant of product.product_variants) {
const prices = variant.product_prices;
if (prices.length > 0) {
return `https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=800&auto=format&fit=crop&q=80`;
}
}
const fallbacks: Record<string, string[]> = {
'daster': [
'https://images.unsplash.com/photo-1595777457583-95e059d581b8?w=800&auto=format&fit=crop&q=80',
'https://images.unsplash.com/photo-1572804013309-59a88b7e92f1?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 categoryUrls = fallbacks[firstCat] || [
'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=800&auto=format&fit=crop&q=80',
'https://images.unsplash.com/photo-1434389677669-e08b4cac3105?w=800&auto=format&fit=crop&q=80',
];
return categoryUrls[0];
}
function getProductPriceRange(product: Product): string {
const prices = product.product_variants.flatMap((v) =>
v.product_prices
.filter((p) => p.type === 'retail')
.map((p) => p.price),
);
if (prices.length === 0) {
const fallbackPrices = product.product_variants.flatMap((v) =>
v.product_prices.map((p) => 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)}`;
}
export default function ProductCard({ product, onQuickView }: ProductCardProps) {
return (
<div
className="group cursor-pointer"
onClick={() => onQuickView(product)}
>
<div className="relative aspect-3/4 rounded-2xl overflow-hidden shadow-md border-2 border-white transition-all duration-300 hover:shadow-xl hover:-translate-y-1">
<img
src={getProductImage(product)}
alt={product.name}
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-black/40 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<div className="absolute bottom-0 left-0 right-0 p-4 translate-y-full group-hover:translate-y-0 transition-transform duration-300">
<span className="text-white text-xs font-semibold uppercase tracking-widest">
Lihat Detail
</span>
</div>
</div>
<div className="mt-4 space-y-1">
<div className="flex items-center gap-2">
{product.categories.slice(0, 2).map((cat) => (
<span
key={cat.id}
className="text-[10px] font-semibold uppercase tracking-wider text-amber-600 bg-amber-50 px-2 py-0.5 rounded-full"
>
{cat.name}
</span>
))}
</div>
<h4 className="text-sm font-semibold text-slate-800 line-clamp-1">
{product.name}
</h4>
<p className="text-xs text-slate-500 line-clamp-2 font-light">
{product.description || 'Koleksi fashion berkualitas'}
</p>
<p className="text-sm font-bold text-amber-600">
{getProductPriceRange(product)}
</p>
</div>
</div>
);
}

View File

@ -0,0 +1,221 @@
import { X, Star, Minus, Plus, Phone } from 'lucide-react';
import { useState } from 'react';
import { formatRupiah } from '@/lib/rupiah';
import type { Product, ProductVariant, ProductPrice } from '@/types/homepage';
type ProductModalProps = {
product: Product | null;
onClose: () => void;
};
function getProductImage(): string {
return 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=1000&auto=format&fit=crop&q=80';
}
function getRetailPrice(variant: ProductVariant): number {
const retail = variant.product_prices.find((p) => p.type === 'retail');
return retail?.price ?? 0;
}
function getWholesalePrice(variant: ProductVariant): number {
const wholesale = variant.product_prices.find((p) => p.type === 'wholesale');
return wholesale?.price ?? 0;
}
export default function ProductModal({ product, onClose }: ProductModalProps) {
const [selectedVariant, setSelectedVariant] = useState<ProductVariant | null>(null);
const [selectedPriceType, setSelectedPriceType] = useState<'retail' | 'wholesale'>('retail');
const [quantity, setQuantity] = useState(1);
if (!product) return null;
const variants = product.product_variants;
const activeVariant = selectedVariant ?? variants[0];
const retailPrice = activeVariant ? getRetailPrice(activeVariant) : 0;
const wholesalePrice = activeVariant ? getWholesalePrice(activeVariant) : 0;
const currentPrice = selectedPriceType === 'retail' ? retailPrice : wholesalePrice;
const maxStock = activeVariant?.stock ?? 0;
const handleWhatsAppOrder = () => {
if (!activeVariant) return;
const priceLabel = selectedPriceType === 'retail' ? 'Retail' : 'Grosir';
const message = `Halo, saya tertarik dengan produk:\n\n*${product.name}*\n- Varian: ${activeVariant.name}\n- Harga ${priceLabel}: Rp ${formatRupiah(currentPrice)}\n- Jumlah: ${quantity} pcs\n- Subtotal: Rp ${formatRupiah(currentPrice * quantity)}\n\nMohon info detail pesanan. Terima kasih!`;
const phone = '6281234567890';
const waUrl = `https://wa.me/${phone}?text=${encodeURIComponent(message)}`;
window.open(waUrl, '_blank');
};
return (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4"
onClick={onClose}
>
<div
className="bg-[#FDFDFC] rounded-3xl max-w-4xl w-full max-h-[90vh] overflow-y-auto shadow-2xl"
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div className="flex justify-between items-center p-6 border-b border-amber-100/30">
<h3 className="text-lg font-serif text-slate-800">Detail Produk</h3>
<button
onClick={onClose}
className="p-2 rounded-full hover:bg-slate-100 transition-colors"
>
<X className="w-5 h-5 text-slate-500" />
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 p-6">
{/* Image */}
<div className="relative aspect-3/4 rounded-2xl overflow-hidden">
<img
src={getProductImage()}
alt={product.name}
className="w-full h-full object-cover"
/>
</div>
{/* Details */}
<div className="space-y-4">
<div>
<div className="flex items-center gap-2 mb-2">
{product.categories.slice(0, 2).map((cat) => (
<span
key={cat.id}
className="text-[10px] font-semibold uppercase tracking-wider text-amber-600 bg-amber-50 px-2 py-0.5 rounded-full"
>
{cat.name}
</span>
))}
</div>
<h2 className="text-2xl font-serif text-slate-800">{product.name}</h2>
</div>
<p className="text-sm text-slate-500 leading-relaxed font-light">
{product.description || 'Produk fashion berkualitas dengan desain elegan dan bahan nyaman.'}
</p>
{/* Rating */}
<div className="flex items-center gap-2">
<div className="flex text-amber-400">
<Star className="w-4 h-4 fill-current" />
<Star className="w-4 h-4 fill-current" />
<Star className="w-4 h-4 fill-current" />
<Star className="w-4 h-4 fill-current" />
<Star className="w-4 h-4 fill-current" />
</div>
<span className="text-xs text-slate-400">5.0 (120+)</span>
</div>
{/* Price */}
<div className="bg-amber-50/50 p-4 rounded-xl">
<p className="text-xs text-slate-500 mb-1">Harga</p>
<p className="text-2xl font-bold text-amber-600">
Rp {formatRupiah(currentPrice)}
</p>
{selectedPriceType === 'wholesale' && wholesalePrice > 0 && (
<p className="text-xs text-slate-400 mt-1">
Harga retail: Rp {formatRupiah(retailPrice)}
</p>
)}
</div>
{/* Variant Selection */}
{variants.length > 0 && (
<div>
<p className="text-xs font-semibold text-slate-700 mb-2">Varian</p>
<div className="flex flex-wrap gap-2">
{variants.map((variant) => (
<button
key={variant.id}
onClick={() => setSelectedVariant(variant)}
className={`px-4 py-2 text-xs font-semibold rounded-xl border transition-all ${
activeVariant?.id === variant.id
? 'bg-amber-600 text-white border-transparent'
: 'bg-white text-slate-600 border-slate-200 hover:border-amber-300'
}`}
>
{variant.name}
<span className="ml-1 text-[10px] opacity-70">
({variant.stock})
</span>
</button>
))}
</div>
</div>
)}
{/* Price Type */}
<div>
<p className="text-xs font-semibold text-slate-700 mb-2">Jenis Harga</p>
<div className="flex gap-2">
<button
onClick={() => setSelectedPriceType('retail')}
className={`px-4 py-2 text-xs font-semibold rounded-xl border transition-all ${
selectedPriceType === 'retail'
? 'bg-amber-600 text-white border-transparent'
: 'bg-white text-slate-600 border-slate-200 hover:border-amber-300'
}`}
>
Retail
</button>
<button
onClick={() => setSelectedPriceType('wholesale')}
className={`px-4 py-2 text-xs font-semibold rounded-xl border transition-all ${
selectedPriceType === 'wholesale'
? 'bg-amber-600 text-white border-transparent'
: 'bg-white text-slate-600 border-slate-200 hover:border-amber-300'
}`}
>
Grosir
</button>
</div>
</div>
{/* Quantity */}
<div>
<p className="text-xs font-semibold text-slate-700 mb-2">Jumlah</p>
<div className="flex items-center gap-3 border border-slate-200 rounded-xl px-3 py-2 w-fit">
<button
onClick={() => setQuantity(Math.max(1, quantity - 1))}
className="p-1 text-slate-500 hover:text-slate-800"
>
<Minus className="w-4 h-4" />
</button>
<span className="text-sm font-semibold w-8 text-center">{quantity}</span>
<button
onClick={() => setQuantity(Math.min(maxStock, quantity + 1))}
className="p-1 text-slate-500 hover:text-slate-800"
>
<Plus className="w-4 h-4" />
</button>
</div>
<p className="text-[10px] text-slate-400 mt-1">Stok tersedia: {maxStock}</p>
</div>
{/* Total */}
<div className="bg-slate-50 p-4 rounded-xl">
<div className="flex justify-between text-sm">
<span className="text-slate-500">Subtotal</span>
<span className="font-bold text-amber-600">
Rp {formatRupiah(currentPrice * quantity)}
</span>
</div>
</div>
{/* WhatsApp Order */}
<button
onClick={handleWhatsAppOrder}
className="w-full flex items-center justify-center bg-emerald-600 text-white hover:bg-emerald-500 py-3.5 text-xs font-bold uppercase tracking-widest rounded-xl transition-all shadow-md"
>
<Phone className="w-4 h-4 mr-2" />
Pesan Via WhatsApp
</button>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,388 +1,621 @@
import { Head, Link, usePage } from '@inertiajs/react';
import { dashboard, login } from '@/routes';
import { register } from '@/routes';
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';
export default function Welcome() {
const { auth } = usePage().props;
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="Welcome" />
<div className="flex min-h-screen flex-col items-center bg-[#FDFDFC] p-6 text-[#1b1b18] lg:justify-center lg:p-8 dark:bg-[#0a0a0a]">
<header className="mb-6 w-full max-w-[335px] text-sm not-has-[nav]:hidden lg:max-w-4xl">
<nav className="flex items-center justify-end gap-4">
{auth.user ? (
<Link
href={dashboard()}
className="inline-block rounded-sm border border-[#19140035] px-5 py-1.5 text-sm leading-normal text-[#1b1b18] hover:border-[#1915014a] dark:border-[#3E3E3A] dark:text-[#EDEDEC] dark:hover:border-[#62605b]"
>
Dashboard
<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>
) : (
<>
<Link
href={login()}
className="inline-block rounded-sm border border-transparent px-5 py-1.5 text-sm leading-normal text-[#1b1b18] hover:border-[#19140035] dark:text-[#EDEDEC] dark:hover:border-[#3E3E3A]"
>
Log in
</Link>
<Link
href={register()}
className="inline-block rounded-sm border border-[#19140035] px-5 py-1.5 text-sm leading-normal text-[#1b1b18] hover:border-[#1915014a] dark:border-[#3E3E3A] dark:text-[#EDEDEC] dark:hover:border-[#62605b]"
>
Register
</Link>
</>
)}
</nav>
</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>
<div className="flex w-full items-center justify-center opacity-100 transition-opacity duration-750 lg:grow starting:opacity-0">
<main className="flex w-full max-w-[335px] flex-col-reverse lg:max-w-4xl lg:flex-row">
<div className="flex-1 rounded-br-lg rounded-bl-lg bg-white p-6 pb-12 text-[13px] leading-[20px] shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-tl-lg lg:rounded-br-none lg:p-20 dark:bg-[#161615] dark:text-[#EDEDEC] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]">
<h1 className="mb-1 font-medium">
Let's get started
{/* 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="mb-2 text-[#706f6c] dark:text-[#A1A09A]">
Laravel has an incredibly rich ecosystem.
<br />
We suggest starting with the following.
<p className="text-sm text-slate-500 max-w-md leading-relaxed font-light">
{homepage.hero_description}
</p>
<ul className="mb-4 flex flex-col lg:mb-6">
<li className="relative flex items-center gap-4 py-2 before:absolute before:top-1/2 before:bottom-0 before:left-[0.4rem] before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]">
<span className="relative bg-white py-1 dark:bg-[#161615]">
<span className="flex h-3.5 w-3.5 items-center justify-center rounded-full border border-[#e3e3e0] bg-[#FDFDFC] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] dark:border-[#3E3E3A] dark:bg-[#161615]">
<span className="h-1.5 w-1.5 rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A]" />
</span>
</span>
<span>
Read the
<a
href="https://laravel.com/docs"
target="_blank"
className="ml-1 inline-flex items-center space-x-1 font-medium text-[#f53003] underline underline-offset-4 dark:text-[#FF4433]"
>
<span>Documentation</span>
<svg
width={10}
height={11}
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-2.5 w-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
strokeLinecap="square"
/>
</svg>
</a>
</span>
</li>
<li className="relative flex items-center gap-4 py-2 before:absolute before:top-0 before:bottom-1/2 before:left-[0.4rem] before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A]">
<span className="relative bg-white py-1 dark:bg-[#161615]">
<span className="flex h-3.5 w-3.5 items-center justify-center rounded-full border border-[#e3e3e0] bg-[#FDFDFC] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] dark:border-[#3E3E3A] dark:bg-[#161615]">
<span className="h-1.5 w-1.5 rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A]" />
</span>
</span>
<span>
Watch video tutorials at
<a
href="https://laracasts.com"
target="_blank"
className="ml-1 inline-flex items-center space-x-1 font-medium text-[#f53003] underline underline-offset-4 dark:text-[#FF4433]"
>
<span>Laracasts</span>
<svg
width={10}
height={11}
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-2.5 w-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
strokeLinecap="square"
/>
</svg>
</a>
</span>
</li>
</ul>
<ul className="flex gap-3 text-sm leading-normal">
<li>
<a
href="https://cloud.laravel.com"
target="_blank"
className="inline-block rounded-sm border border-black bg-[#1b1b18] px-5 py-1.5 text-sm leading-normal text-white hover:border-black hover:bg-black dark:border-[#eeeeec] dark:bg-[#eeeeec] dark:text-[#1C1C1A] dark:hover:border-white dark:hover:bg-white"
<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'
}`}
>
Deploy now
</a>
</li>
{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="relative -mb-px aspect-[335/364] w-full shrink-0 overflow-hidden rounded-t-lg bg-[#fff2f2] lg:mb-0 lg:-ml-px lg:aspect-auto lg:w-[438px] lg:rounded-t-none lg:rounded-r-lg dark:bg-[#1D0002]">
{/* Laravel Logo */}
<svg
className="w-full max-w-none translate-y-0 text-[#F53003] opacity-100 transition-all duration-750 dark:text-[#F61500] starting:opacity-0 motion-safe:starting:translate-y-6"
viewBox="0 0 438 104"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.2036 -3H0V102.197H49.5189V86.7187H17.2036V-3Z"
fill="currentColor"
/>
<path
d="M110.256 41.6337C108.061 38.1275 104.945 35.3731 100.905 33.3681C96.8667 31.3647 92.8016 30.3618 88.7131 30.3618C83.4247 30.3618 78.5885 31.3389 74.201 33.2923C69.8111 35.2456 66.0474 37.928 62.9059 41.3333C59.7643 44.7401 57.3198 48.6726 55.5754 53.1293C53.8287 57.589 52.9572 62.274 52.9572 67.1813C52.9572 72.1925 53.8287 76.8995 55.5754 81.3069C57.3191 85.7173 59.7636 89.6241 62.9059 93.0293C66.0474 96.4361 69.8119 99.1155 74.201 101.069C78.5885 103.022 83.4247 103.999 88.7131 103.999C92.8016 103.999 96.8667 102.997 100.905 100.994C104.945 98.9911 108.061 96.2359 110.256 92.7282V102.195H126.563V32.1642H110.256V41.6337ZM108.76 75.7472C107.762 78.4531 106.366 80.8078 104.572 82.8112C102.776 84.8161 100.606 86.4183 98.0637 87.6206C95.5202 88.823 92.7004 89.4238 89.6103 89.4238C86.5178 89.4238 83.7252 88.823 81.2324 87.6206C78.7388 86.4183 76.5949 84.8161 74.7998 82.8112C73.004 80.8078 71.6319 78.4531 70.6856 75.7472C69.7356 73.0421 69.2644 70.1868 69.2644 67.1821C69.2644 64.1758 69.7356 61.3205 70.6856 58.6154C71.6319 55.9102 73.004 53.5571 74.7998 51.5522C76.5949 49.5495 78.738 47.9451 81.2324 46.7427C83.7252 45.5404 86.5178 44.9396 89.6103 44.9396C92.7012 44.9396 95.5202 45.5404 98.0637 46.7427C100.606 47.9451 102.776 49.5487 104.572 51.5522C106.367 53.5571 107.762 55.9102 108.76 58.6154C109.756 61.3205 110.256 64.1758 110.256 67.1821C110.256 70.1868 109.756 73.0421 108.76 75.7472Z"
fill="currentColor"
/>
<path
d="M242.805 41.6337C240.611 38.1275 237.494 35.3731 233.455 33.3681C229.416 31.3647 225.351 30.3618 221.262 30.3618C215.974 30.3618 211.138 31.3389 206.75 33.2923C202.36 35.2456 198.597 37.928 195.455 41.3333C192.314 44.7401 189.869 48.6726 188.125 53.1293C186.378 57.589 185.507 62.274 185.507 67.1813C185.507 72.1925 186.378 76.8995 188.125 81.3069C189.868 85.7173 192.313 89.6241 195.455 93.0293C198.597 96.4361 202.361 99.1155 206.75 101.069C211.138 103.022 215.974 103.999 221.262 103.999C225.351 103.999 229.416 102.997 233.455 100.994C237.494 98.9911 240.611 96.2359 242.805 92.7282V102.195H259.112V32.1642H242.805V41.6337ZM241.31 75.7472C240.312 78.4531 238.916 80.8078 237.122 82.8112C235.326 84.8161 233.156 86.4183 230.614 87.6206C228.07 88.823 225.251 89.4238 222.16 89.4238C219.068 89.4238 216.275 88.823 213.782 87.6206C211.289 86.4183 209.145 84.8161 207.35 82.8112C205.554 80.8078 204.182 78.4531 203.236 75.7472C202.286 73.0421 201.814 70.1868 201.814 67.1821C201.814 64.1758 202.286 61.3205 203.236 58.6154C204.182 55.9102 205.554 53.5571 207.35 51.5522C209.145 49.5495 211.288 47.9451 213.782 46.7427C216.275 45.5404 219.068 44.9396 222.16 44.9396C225.251 44.9396 228.07 45.5404 230.614 46.7427C233.156 47.9451 235.326 49.5487 237.122 51.5522C238.917 53.5571 240.312 55.9102 241.31 58.6154C242.306 61.3205 242.806 64.1758 242.806 67.1821C242.805 70.1868 242.305 73.0421 241.31 75.7472Z"
fill="currentColor"
/>
<path
d="M438 -3H421.694V102.197H438V-3Z"
fill="currentColor"
/>
<path
d="M139.43 102.197H155.735V48.2834H183.712V32.1665H139.43V102.197Z"
fill="currentColor"
/>
<path
d="M324.49 32.1665L303.995 85.794L283.498 32.1665H266.983L293.748 102.197H314.242L341.006 32.1665H324.49Z"
fill="currentColor"
/>
<path
d="M376.571 30.3656C356.603 30.3656 340.797 46.8497 340.797 67.1828C340.797 89.6597 356.094 104 378.661 104C391.29 104 399.354 99.1488 409.206 88.5848L398.189 80.0226C398.183 80.031 389.874 90.9895 377.468 90.9895C363.048 90.9895 356.977 79.3111 356.977 73.269H411.075C413.917 50.1328 398.775 30.3656 376.571 30.3656ZM357.02 61.0967C357.145 59.7487 359.023 43.3761 376.442 43.3761C393.861 43.3761 395.978 59.7464 396.099 61.0967H357.02Z"
fill="currentColor"
/>
</svg>
{/* 13 */}
<svg
className="relative -mt-[6.6rem] -ml-8 w-[438px] max-w-none [--stroke-color:#1B1B18] lg:ml-0 dark:[--stroke-color:#FF750F]"
viewBox="0 0 440 392"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g className="text-[#1B1B18] opacity-100 mix-blend-darken transition-all delay-300 duration-750 dark:text-black dark:mix-blend-normal starting:opacity-0">
<mask
id="path-1-mask"
maskUnits="userSpaceOnUse"
x="-0.328613"
y="103"
width="338"
height="299"
fill="black"
>
<rect
fill="white"
x="-0.328613"
y="103"
width="338"
height="299"
/>
<path d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z" />
<path d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z" />
</mask>
<path
d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z"
fill="currentColor"
/>
<path
d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z"
fill="currentColor"
/>
<path
d="M234.936 400.8C204.136 400.8 178.936 392.4 159.336 375.6C140.136 358.8 130.536 337 130.536 310.2H200.736C200.736 318.2 203.736 324.8 209.736 330C215.736 335.2 223.736 337.8 233.736 337.8C243.336 337.8 251.136 335 257.136 329.4C263.536 323.8 266.736 316.6 266.736 307.8C266.736 299.8 263.936 293.2 258.336 288C252.736 282.8 245.536 280.2 236.736 280.2H199.536V218.4H236.736C243.536 218.4 249.336 216 254.136 211.2C258.936 206.4 261.336 200.4 261.336 193.2C261.336 184.8 258.736 178.2 253.536 173.4C248.336 168.6 241.736 166.2 233.736 166.2C226.536 166.2 220.336 168.4 215.136 172.8C210.336 177.2 207.936 182.8 207.936 189.6H141.336C141.336 164.8 150.136 144.6 167.736 129C185.336 113 207.936 105 235.536 105C263.136 105 285.536 112.2 302.736 126.6C320.336 141 329.136 160 329.136 183.6C329.136 200.8 324.536 214.8 315.336 225.6C306.136 236 294.336 243.2 279.936 247.2C297.136 252 310.736 260.2 320.736 271.8C331.136 283.4 336.336 298 336.336 315.6C336.336 340.4 326.936 360.8 308.136 376.8C289.336 392.8 264.936 400.8 234.936 400.8Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-1-mask)"
/>
<path
d="M26.8714 167.6H1.67139V105.2H94.6714V400.2H26.8714V167.6Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-1-mask)"
/>
</g>
<g className="text-[#F3BEC7] opacity-100 transition-all delay-400 duration-750 dark:text-[#4B0600] starting:opacity-0 motion-safe:starting:-translate-x-[26px]">
<mask
id="path-2-mask"
maskUnits="userSpaceOnUse"
x="25.3357"
y="103"
width="338"
height="299"
fill="black"
>
<rect
fill="white"
x="25.3357"
y="103"
width="338"
height="299"
/>
<path d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z" />
<path d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z" />
</mask>
<path
d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z"
fill="currentColor"
/>
<path
d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z"
fill="currentColor"
/>
<path
d="M260.6 400.8C229.8 400.8 204.6 392.4 185 375.6C165.8 358.8 156.2 337 156.2 310.2H226.4C226.4 318.2 229.4 324.8 235.4 330C241.4 335.2 249.4 337.8 259.4 337.8C269 337.8 276.8 335 282.8 329.4C289.2 323.8 292.4 316.6 292.4 307.8C292.4 299.8 289.6 293.2 284 288C278.4 282.8 271.2 280.2 262.4 280.2H225.2V218.4H262.4C269.2 218.4 275 216 279.8 211.2C284.6 206.4 287 200.4 287 193.2C287 184.8 284.4 178.2 279.2 173.4C274 168.6 267.4 166.2 259.4 166.2C252.2 166.2 246 168.4 240.8 172.8C236 177.2 233.6 182.8 233.6 189.6H167C167 164.8 175.8 144.6 193.4 129C211 113 233.6 105 261.2 105C288.8 105 311.2 112.2 328.4 126.6C346 141 354.8 160 354.8 183.6C354.8 200.8 350.2 214.8 341 225.6C331.8 236 320 243.2 305.6 247.2C322.8 252 336.4 260.2 346.4 271.8C356.8 283.4 362 298 362 315.6C362 340.4 352.6 360.8 333.8 376.8C315 392.8 290.6 400.8 260.6 400.8Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-2-mask)"
/>
<path
d="M52.5357 167.6H27.3357V105.2H120.336V400.2H52.5357V167.6Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-2-mask)"
/>
</g>
<g className="text-[#F8B803] opacity-100 mix-blend-color transition-all delay-400 duration-750 dark:text-[#391800] dark:mix-blend-hard-light starting:opacity-0 motion-safe:starting:-translate-x-[51px]">
<mask
id="path-3-mask"
maskUnits="userSpaceOnUse"
x="51"
y="103"
width="338"
height="299"
fill="black"
>
<rect
fill="white"
x="51"
y="103"
width="338"
height="299"
/>
<path d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z" />
<path d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z" />
</mask>
<path
d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z"
fill="currentColor"
/>
<path
d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z"
fill="currentColor"
/>
<path
d="M286.264 400.8C255.464 400.8 230.264 392.4 210.664 375.6C191.464 358.8 181.864 337 181.864 310.2H252.064C252.064 318.2 255.064 324.8 261.064 330C267.064 335.2 275.064 337.8 285.064 337.8C294.664 337.8 302.464 335 308.464 329.4C314.864 323.8 318.064 316.6 318.064 307.8C318.064 299.8 315.264 293.2 309.664 288C304.064 282.8 296.864 280.2 288.064 280.2H250.864V218.4H288.064C294.864 218.4 300.664 216 305.464 211.2C310.264 206.4 312.664 200.4 312.664 193.2C312.664 184.8 310.064 178.2 304.864 173.4C299.664 168.6 293.064 166.2 285.064 166.2C277.864 166.2 271.664 168.4 266.464 172.8C261.664 177.2 259.264 182.8 259.264 189.6H192.664C192.664 164.8 201.464 144.6 219.064 129C236.664 113 259.264 105 286.864 105C314.464 105 336.864 112.2 354.064 126.6C371.664 141 380.464 160 380.464 183.6C380.464 200.8 375.864 214.8 366.664 225.6C357.464 236 345.664 243.2 331.264 247.2C348.464 252 362.064 260.2 372.064 271.8C382.464 283.4 387.664 298 387.664 315.6C387.664 340.4 378.264 360.8 359.464 376.8C340.664 392.8 316.264 400.8 286.264 400.8Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-3-mask)"
/>
<path
d="M78.2 167.6H53V105.2H146V400.2H78.2V167.6Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-3-mask)"
/>
</g>
<g className="text-[#F3BEC7] opacity-100 mix-blend-multiply transition-all delay-400 duration-750 dark:text-[#733000] dark:mix-blend-normal starting:opacity-0 motion-safe:starting:-translate-x-[78px]">
<mask
id="path-4-mask"
maskUnits="userSpaceOnUse"
x="76.6643"
y="103"
width="338"
height="299"
fill="black"
>
<rect
fill="white"
x="76.6643"
y="103"
width="338"
height="299"
/>
<path d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z" />
<path d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z" />
</mask>
<path
d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z"
fill="currentColor"
/>
<path
d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z"
fill="currentColor"
/>
<path
d="M311.929 400.8C281.129 400.8 255.929 392.4 236.329 375.6C217.129 358.8 207.529 337 207.529 310.2H277.729C277.729 318.2 280.729 324.8 286.729 330C292.729 335.2 300.729 337.8 310.729 337.8C320.329 337.8 328.129 335 334.129 329.4C340.529 323.8 343.729 316.6 343.729 307.8C343.729 299.8 340.929 293.2 335.329 288C329.729 282.8 322.529 280.2 313.729 280.2H276.529V218.4H313.729C320.529 218.4 326.329 216 331.129 211.2C335.929 206.4 338.329 200.4 338.329 193.2C338.329 184.8 335.729 178.2 330.529 173.4C325.329 168.6 318.729 166.2 310.729 166.2C303.529 166.2 297.329 168.4 292.129 172.8C287.329 177.2 284.929 182.8 284.929 189.6H218.329C218.329 164.8 227.129 144.6 244.729 129C262.329 113 284.929 105 312.529 105C340.129 105 362.529 112.2 379.729 126.6C397.329 141 406.129 160 406.129 183.6C406.129 200.8 401.529 214.8 392.329 225.6C383.129 236 371.329 243.2 356.929 247.2C374.129 252 387.729 260.2 397.729 271.8C408.129 283.4 413.329 298 413.329 315.6C413.329 340.4 403.929 360.8 385.129 376.8C366.329 392.8 341.929 400.8 311.929 400.8Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-4-mask)"
/>
<path
d="M103.864 167.6H78.6643V105.2H171.664V400.2H103.864V167.6Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-4-mask)"
/>
</g>
<g className="text-[#F3BEC7] opacity-100 mix-blend-hard-light transition-all delay-400 duration-750 dark:text-[#4B0600] starting:opacity-0 motion-safe:starting:-translate-x-[102px]">
<mask
id="path-5-mask"
maskUnits="userSpaceOnUse"
x="102.329"
y="103"
width="338"
height="299"
fill="black"
>
<rect
fill="white"
x="102.329"
y="103"
width="338"
height="299"
/>
<path d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z" />
<path d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z" />
</mask>
<path
d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z"
fill="currentColor"
/>
<path
d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z"
fill="currentColor"
/>
<path
d="M337.593 400.8C306.793 400.8 281.593 392.4 261.993 375.6C242.793 358.8 233.193 337 233.193 310.2H303.393C303.393 318.2 306.393 324.8 312.393 330C318.393 335.2 326.393 337.8 336.393 337.8C345.993 337.8 353.793 335 359.793 329.4C366.193 323.8 369.393 316.6 369.393 307.8C369.393 299.8 366.593 293.2 360.993 288C355.393 282.8 348.193 280.2 339.393 280.2H302.193V218.4H339.393C346.193 218.4 351.993 216 356.793 211.2C361.593 206.4 363.993 200.4 363.993 193.2C363.993 184.8 361.393 178.2 356.193 173.4C350.993 168.6 344.393 166.2 336.393 166.2C329.193 166.2 322.993 168.4 317.793 172.8C312.993 177.2 310.593 182.8 310.593 189.6H243.993C243.993 164.8 252.793 144.6 270.393 129C287.993 113 310.593 105 338.193 105C365.793 105 388.193 112.2 405.393 126.6C422.993 141 431.793 160 431.793 183.6C431.793 200.8 427.193 214.8 417.993 225.6C408.793 236 396.993 243.2 382.593 247.2C399.793 252 413.393 260.2 423.393 271.8C433.793 283.4 438.993 298 438.993 315.6C438.993 340.4 429.593 360.8 410.793 376.8C391.993 392.8 367.593 400.8 337.593 400.8Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-5-mask)"
/>
<path
d="M129.529 167.6H104.329V105.2H197.329V400.2H129.529V167.6Z"
stroke="var(--stroke-color)"
strokeWidth="2.4"
mask="url(#path-5-mask)"
/>
</g>
</svg>
<div className="absolute inset-0 rounded-t-lg shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] lg:rounded-t-none lg:rounded-r-lg dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]"></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>
</main>
</div>
<div className="hidden h-14.5 lg:block"></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>
</>
);

View File

@ -0,0 +1,101 @@
export type ProductPrice = {
id: number;
variant_id: number;
type: string;
type_label: string;
price: number;
formatted_price: string;
};
export type ProductVariant = {
id: number;
product_id: number;
name: string;
stock: number;
formatted_stock: string;
product_prices: ProductPrice[];
};
export type ProductCategory = {
id: number;
name: string;
slug: string;
};
export type Product = {
id: number;
name: string;
slug: string;
description: string | null;
status: string;
formatted_name: string;
status_label: string;
categories: ProductCategory[];
product_variants: ProductVariant[];
};
export type Category = {
id: number;
name: string;
slug: string;
formatted_name: string;
};
export type HomepageData = {
hero_badge: string;
hero_title_line1: string;
hero_title_line2: string;
hero_title_highlight: string;
hero_description: string;
hero_cta_primary_text: string;
hero_cta_secondary_text: string;
hero_image_url: string | null;
hero_bg_text_left: string;
hero_bg_text_right: string;
scroll_hashtag: string;
scroll_tagline: string;
catalog_badge: string;
catalog_title: string;
catalog_description: string;
catalog_search_placeholder: string;
gallery_badge: string;
gallery_title: string;
gallery_description: string;
gallery_images: string[];
order_guide_badge: string;
order_guide_title: string;
order_guide_description: string;
order_steps: Array<{ title: string; description: string }>;
about_badge: string;
about_title: string;
about_image_url: string | null;
about_features: string[];
contact_badge: string;
contact_title: string;
contact_description: string;
contact_form_title: string;
footer_description: string;
footer_copyright: string;
};
export type Paginated<T> = {
data: T[];
current_page: number;
first_page_url: string;
from: number;
last_page: number;
last_page_url: string;
next_page_url: string | null;
path: string;
per_page: number;
prev_page_url: string | null;
to: number;
total: number;
};
export type SeoData = {
title: string;
description: string;
image: string;
url: string;
};

View File

@ -1,3 +1,4 @@
export type * from './auth';
export type * from './homepage';
export type * from './navigation';
export type * from './ui';

View File

@ -25,16 +25,10 @@
use App\Http\Controllers\Admin\RoleController;
use App\Http\Controllers\AnalysisController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\HomepageController;
use Illuminate\Support\Facades\Route;
Route::get('/', fn() => inertia('welcome', [
'seo' => [
'title' => 'DST Collection - DST Punya Gaya',
'description' => 'DST Collection - DST Punya Gaya. Toko fashion terpercaya dengan koleksi terlengkap.',
'image' => url('/assets/logo.png'),
'url' => url('/'),
],
]))->name('home');
Route::get('/', HomepageController::class)->name('home');
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('dashboard', DashboardController::class)->name('dashboard');