280 lines
16 KiB
TypeScript
280 lines
16 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import type { ReactElement } from 'react';
|
|
import Head from 'next/head';
|
|
import Link from 'next/link';
|
|
import BaseButton from '../components/BaseButton';
|
|
import LayoutGuest from '../layouts/Guest';
|
|
import { getPageTitle } from '../config';
|
|
import { useAppSelector, useAppDispatch } from '../stores/hooks';
|
|
import { fetch as fetchProducts } from '../stores/products/productsSlice';
|
|
import { fetch as fetchCategories } from '../stores/product_categories/product_categoriesSlice';
|
|
import ImageField from '../components/ImageField';
|
|
import { mdiCartOutline, mdiArrowRight } from '@mdi/js';
|
|
import BaseIcon from '../components/BaseIcon';
|
|
import LoadingSpinner from '../components/LoadingSpinner';
|
|
import CartDrawer from '../components/CartDrawer';
|
|
import { addToCart, toggleCart } from '../stores/localCartSlice';
|
|
|
|
export default function Home() {
|
|
const dispatch = useAppDispatch();
|
|
const { products, loading: productsLoading } = useAppSelector((state) => state.products);
|
|
const { product_categories, loading: categoriesLoading } = useAppSelector((state) => state.product_categories);
|
|
const { currentUser } = useAppSelector((state) => state.auth);
|
|
const darkMode = useAppSelector((state) => state.style.darkMode);
|
|
const { items: cartItems } = useAppSelector((state) => state.localCart);
|
|
|
|
const cartCount = cartItems.reduce((sum, item) => sum + item.quantity, 0);
|
|
|
|
useEffect(() => {
|
|
dispatch(fetchProducts({ query: '?limit=8' }));
|
|
dispatch(fetchCategories({ query: '' }));
|
|
}, [dispatch]);
|
|
|
|
const handleAddToCart = (product: any) => {
|
|
dispatch(addToCart({
|
|
id: product.id,
|
|
name: product.name,
|
|
price: product.price,
|
|
quantity: 1,
|
|
image: product.images ? product.images[0]?.url : null
|
|
}));
|
|
dispatch(toggleCart());
|
|
};
|
|
|
|
const heroImage = "https://images.pexels.com/photos/958545/pexels-photo-958545.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1";
|
|
|
|
return (
|
|
<div className={`min-h-screen ${darkMode ? 'bg-dark-900 text-white' : 'bg-gray-50 text-gray-900'}`}>
|
|
<Head>
|
|
<title>{getPageTitle('El Calentico - Tu Tienda Virtual')}</title>
|
|
</Head>
|
|
|
|
<CartDrawer />
|
|
|
|
{/* Navigation / Header */}
|
|
<nav className={`sticky top-0 z-40 w-full border-b ${darkMode ? 'bg-dark-800 border-dark-700' : 'bg-white border-gray-200'} px-4 py-3 shadow-sm`}>
|
|
<div className="container mx-auto flex items-center justify-between">
|
|
<Link href="/" className="flex items-center gap-2">
|
|
<span className="text-2xl font-bold text-orange-600">El Calentico</span>
|
|
</Link>
|
|
<div className="flex items-center gap-4">
|
|
<Link href="/search" className="hidden md:block text-sm font-medium hover:text-orange-600 transition-colors">
|
|
Buscar
|
|
</Link>
|
|
|
|
{/* Cart Toggle Button */}
|
|
<button
|
|
onClick={() => dispatch(toggleCart())}
|
|
className="relative p-2 text-gray-600 hover:text-orange-600 transition-colors"
|
|
>
|
|
<BaseIcon path={mdiCartOutline} size={28} />
|
|
{cartCount > 0 && (
|
|
<span className="absolute top-0 right-0 bg-orange-600 text-white text-[10px] font-bold w-5 h-5 flex items-center justify-center rounded-full border-2 border-white">
|
|
{cartCount}
|
|
</span>
|
|
)}
|
|
</button>
|
|
|
|
{currentUser ? (
|
|
<Link href="/dashboard" className="text-sm font-medium px-4 py-2 rounded-full bg-orange-600 text-white hover:bg-orange-700 transition-colors">
|
|
Dashboard
|
|
</Link>
|
|
) : (
|
|
<div className="flex items-center gap-2">
|
|
<Link href="/login" className="hidden sm:block text-sm font-medium hover:text-orange-600 transition-colors">
|
|
Iniciar Sesión
|
|
</Link>
|
|
<Link href="/register" className="text-sm font-medium px-4 py-2 rounded-full bg-orange-600 text-white hover:bg-orange-700 transition-colors">
|
|
Registrarse
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Hero Section */}
|
|
<section className="relative h-[500px] w-full overflow-hidden flex items-center">
|
|
<div className="absolute inset-0 z-0">
|
|
<img src={heroImage} alt="Food hero" className="w-full h-full object-cover" />
|
|
<div className="absolute inset-0 bg-black/40"></div>
|
|
</div>
|
|
<div className="container mx-auto relative z-10 px-4">
|
|
<div className="max-w-2xl text-white">
|
|
<h1 className="text-5xl md:text-6xl font-extrabold mb-6 leading-tight">
|
|
Sabor y Frescura <br />
|
|
<span className="text-orange-400">Directo a tu Mesa</span>
|
|
</h1>
|
|
<p className="text-xl mb-8 text-gray-100">
|
|
Descubre la mejor selección de alimentos, bebidas y productos locales en El Calentico. Calidad garantizada en cada pedido.
|
|
</p>
|
|
<div className="flex gap-4">
|
|
<BaseButton
|
|
label="Comprar Ahora"
|
|
color="warning"
|
|
roundedFull
|
|
className="px-8 py-3 text-lg font-bold"
|
|
href="#products"
|
|
/>
|
|
<BaseButton
|
|
label="Ver Categorías"
|
|
color="white"
|
|
outline
|
|
roundedFull
|
|
className="px-8 py-3 text-lg font-bold"
|
|
href="#categories"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Categories Section */}
|
|
<section id="categories" className="py-16 bg-white dark:bg-dark-800">
|
|
<div className="container mx-auto px-4">
|
|
<div className="flex justify-between items-end mb-10">
|
|
<div>
|
|
<h2 className="text-3xl font-bold mb-2">Categorías</h2>
|
|
<p className="text-gray-500">Explora nuestra variedad de productos</p>
|
|
</div>
|
|
</div>
|
|
|
|
{categoriesLoading ? (
|
|
<div className="flex justify-center py-10"><LoadingSpinner /></div>
|
|
) : (
|
|
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
|
|
{product_categories?.map((cat: any) => (
|
|
<Link
|
|
key={cat.id}
|
|
href={`/search?category=${cat.id}`}
|
|
className={`group flex flex-col items-center p-6 rounded-2xl transition-all hover:shadow-lg ${darkMode ? 'bg-dark-700 border-dark-600 hover:bg-dark-600' : 'bg-gray-50 border-gray-100 hover:bg-orange-50 hover:border-orange-200'} border`}
|
|
>
|
|
<div className="w-16 h-16 bg-orange-100 rounded-full flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
|
|
<span className="text-2xl font-bold text-orange-600">{cat.name.charAt(0)}</span>
|
|
</div>
|
|
<span className="font-semibold text-center group-hover:text-orange-600">{cat.name}</span>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Featured Products */}
|
|
<section id="products" className="py-16">
|
|
<div className="container mx-auto px-4">
|
|
<div className="flex justify-between items-end mb-10">
|
|
<div>
|
|
<h2 className="text-3xl font-bold mb-2">Productos Destacados</h2>
|
|
<p className="text-gray-500">Lo más buscado de esta semana</p>
|
|
</div>
|
|
<Link href="/search" className="text-orange-600 font-bold flex items-center gap-1 hover:underline">
|
|
Ver todos <BaseIcon path={mdiArrowRight} size={20} />
|
|
</Link>
|
|
</div>
|
|
|
|
{productsLoading ? (
|
|
<div className="flex justify-center py-10"><LoadingSpinner /></div>
|
|
) : (
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
|
|
{products?.map((product: any) => (
|
|
<div key={product.id} className={`group flex flex-col overflow-hidden rounded-2xl shadow-sm border transition-all hover:shadow-xl ${darkMode ? 'bg-dark-800 border-dark-700' : 'bg-white border-gray-200'}`}>
|
|
<Link href={`/products/products-view/?id=${product.id}`} className="relative h-64 overflow-hidden">
|
|
<ImageField
|
|
image={product.images}
|
|
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
|
|
/>
|
|
{product.price < product.compare_at_price && (
|
|
<div className="absolute top-4 left-4 bg-red-600 text-white text-xs font-bold px-3 py-1 rounded-full">
|
|
OFERTA
|
|
</div>
|
|
)}
|
|
</Link>
|
|
<div className="p-6 flex flex-col flex-grow">
|
|
<div className="text-xs text-gray-500 mb-2 uppercase tracking-wider font-semibold">
|
|
{product.category?.name || 'Producto'}
|
|
</div>
|
|
<Link href={`/products/products-view/?id=${product.id}`}>
|
|
<h3 className="text-lg font-bold mb-2 group-hover:text-orange-600 transition-colors line-clamp-2">{product.name}</h3>
|
|
</Link>
|
|
<div className="mt-auto flex items-center justify-between">
|
|
<div className="flex flex-col">
|
|
{product.compare_at_price > 0 && (
|
|
<span className="text-sm text-gray-400 line-through">${product.compare_at_price}</span>
|
|
)}
|
|
<span className="text-2xl font-extrabold text-orange-600">${product.price}</span>
|
|
</div>
|
|
<button
|
|
onClick={() => handleAddToCart(product)}
|
|
className="p-3 bg-gray-100 hover:bg-orange-600 hover:text-white rounded-full transition-all duration-300 group/cart"
|
|
title="Añadir al carrito"
|
|
>
|
|
<BaseIcon path={mdiCartOutline} size={24} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
|
|
{/* CTA Section */}
|
|
<section className="py-20 bg-orange-600 text-white">
|
|
<div className="container mx-auto px-4 text-center">
|
|
<h2 className="text-4xl font-bold mb-6">¿Listo para hacer tu primer pedido?</h2>
|
|
<p className="text-xl mb-10 max-w-2xl mx-auto opacity-90">
|
|
Únete a miles de clientes satisfechos que ya disfrutan de la frescura de El Calentico en sus hogares.
|
|
</p>
|
|
<BaseButton
|
|
label="Crear una Cuenta Gratis"
|
|
color="white"
|
|
roundedFull
|
|
className="px-10 py-4 text-lg font-bold text-orange-600"
|
|
href="/register"
|
|
/>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Footer */}
|
|
<footer className={`py-12 ${darkMode ? 'bg-dark-800 text-gray-400' : 'bg-gray-100 text-gray-600'}`}>
|
|
<div className="container mx-auto px-4">
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-12 mb-12">
|
|
<div className="col-span-1 md:col-span-2">
|
|
<h3 className="text-2xl font-bold text-orange-600 mb-6">El Calentico</h3>
|
|
<p className="mb-6 max-w-md">
|
|
Tu tienda virtual de confianza para alimentos, bebidas y productos del día a día. Llevamos la mejor calidad directamente a tu puerta.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<h4 className="text-lg font-bold mb-6 text-gray-900 dark:text-white">Enlaces Rápidos</h4>
|
|
<ul className="space-y-4">
|
|
<li><Link href="/search" className="hover:text-orange-600 transition-colors">Productos</Link></li>
|
|
<li><Link href="#categories" className="hover:text-orange-600 transition-colors">Categorías</Link></li>
|
|
<li><Link href="/login" className="hover:text-orange-600 transition-colors">Mi Cuenta</Link></li>
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<h4 className="text-lg font-bold mb-6 text-gray-900 dark:text-white">Legal</h4>
|
|
<ul className="space-y-4">
|
|
<li><Link href="/privacy-policy" className="hover:text-orange-600 transition-colors">Privacidad</Link></li>
|
|
<li><Link href="/terms-of-use" className="hover:text-orange-600 transition-colors">Términos</Link></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div className="border-t border-gray-200 dark:border-dark-700 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
|
<p className="text-sm">© 2026 El Calentico. Todos los derechos reservados.</p>
|
|
<div className="flex gap-6">
|
|
{/* Social icons could go here */}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
Home.getLayout = function getLayout(page: ReactElement) {
|
|
return <LayoutGuest>{page}</LayoutGuest>;
|
|
}; |