import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Store, Search, Star, Heart, ShoppingCart, Package, Truck, Clock, CheckCircle, XCircle, MapPin, Phone, ChevronRight, } from 'lucide-react'; import clsx from 'clsx'; import { marketplaceApi } from '../lib/api'; const categories = [ { id: 'bebidas', name: 'Bebidas', icon: '๐Ÿฅค' }, { id: 'botanas', name: 'Botanas', icon: '๐Ÿฟ' }, { id: 'lacteos', name: 'Lacteos', icon: '๐Ÿฅ›' }, { id: 'pan', name: 'Pan', icon: '๐Ÿž' }, { id: 'abarrotes', name: 'Abarrotes', icon: '๐Ÿ›’' }, { id: 'limpieza', name: 'Limpieza', icon: '๐Ÿงน' }, ]; const orderStatusConfig = { pending: { label: 'Pendiente', color: 'yellow', icon: Clock }, confirmed: { label: 'Confirmado', color: 'blue', icon: CheckCircle }, preparing: { label: 'Preparando', color: 'indigo', icon: Package }, shipped: { label: 'En camino', color: 'purple', icon: Truck }, delivered: { label: 'Entregado', color: 'green', icon: CheckCircle }, cancelled: { label: 'Cancelado', color: 'red', icon: XCircle }, rejected: { label: 'Rechazado', color: 'red', icon: XCircle }, }; export function Marketplace() { const [view, setView] = useState<'suppliers' | 'orders' | 'favorites'>('suppliers'); const [selectedCategory, setSelectedCategory] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [selectedSupplier, setSelectedSupplier] = useState(null); const [showCart, setShowCart] = useState(false); const [cart, setCart] = useState<{ product: any; quantity: number }[]>([]); const queryClient = useQueryClient(); const { data: suppliers = [], isLoading: loadingSuppliers } = useQuery({ queryKey: ['suppliers', selectedCategory, searchQuery], queryFn: async () => { const response = await marketplaceApi.getSuppliers({ category: selectedCategory || undefined, search: searchQuery || undefined, }); return response.data; }, }); const { data: orders = [], isLoading: loadingOrders } = useQuery({ queryKey: ['marketplace-orders'], queryFn: async () => { const response = await marketplaceApi.getOrders(); return response.data; }, enabled: view === 'orders', }); const { data: favorites = [] } = useQuery({ queryKey: ['supplier-favorites'], queryFn: async () => { const response = await marketplaceApi.getFavorites(); return response.data; }, enabled: view === 'favorites', }); const addToCart = (product: any) => { const existing = cart.find((item) => item.product.id === product.id); if (existing) { setCart( cart.map((item) => item.product.id === product.id ? { ...item, quantity: item.quantity + 1 } : item ) ); } else { setCart([...cart, { product, quantity: 1 }]); } }; const removeFromCart = (productId: string) => { setCart(cart.filter((item) => item.product.id !== productId)); }; const updateCartQuantity = (productId: string, quantity: number) => { if (quantity <= 0) { removeFromCart(productId); } else { setCart( cart.map((item) => item.product.id === productId ? { ...item, quantity } : item ) ); } }; const cartTotal = cart.reduce( (sum, item) => sum + Number(item.product.unitPrice) * item.quantity, 0 ); return (

Marketplace

Encuentra proveedores para tu negocio

{cart.length > 0 && ( )}
{/* Tabs */}
{view === 'suppliers' && ( <> {/* Search & Filter */}
setSearchQuery(e.target.value)} placeholder="Buscar proveedores..." className="input pl-10" />
{/* Categories */}
{categories.map((category) => ( ))}
{/* Suppliers Grid */} {loadingSuppliers ? (

Buscando proveedores...

) : suppliers.length === 0 ? (

No hay proveedores

Pronto habra mas proveedores disponibles

) : (
{suppliers.map((supplier: any) => ( setSelectedSupplier(supplier)} /> ))}
)} )} {view === 'orders' && (
{loadingOrders ? (
) : orders.length === 0 ? (

No hay pedidos

Tus pedidos a proveedores apareceran aqui

) : ( orders.map((order: any) => ( )) )}
)} {view === 'favorites' && (
{favorites.length === 0 ? (

Sin favoritos

Agrega proveedores a tus favoritos

) : ( favorites.map((supplier: any) => ( setSelectedSupplier(supplier)} /> )) )}
)} {/* Supplier Detail Modal */} {selectedSupplier && ( setSelectedSupplier(null)} onAddToCart={addToCart} cart={cart} /> )} {/* Cart Modal */} {showCart && ( setShowCart(false)} onUpdateQuantity={updateCartQuantity} onRemove={removeFromCart} onOrderSuccess={() => { setCart([]); setShowCart(false); queryClient.invalidateQueries({ queryKey: ['marketplace-orders'] }); }} /> )}
); } function SupplierCard({ supplier, onClick, }: { supplier: any; onClick: () => void; }) { return (
{supplier.logoUrl ? ( {supplier.name} ) : ( )}

{supplier.name}

{supplier.verified && ( )}
{Number(supplier.rating).toFixed(1)}
ยท {supplier.totalReviews} resenas
{supplier.categories?.slice(0, 3).map((cat: string) => ( {cat} ))}
Min: ${Number(supplier.minOrderAmount).toFixed(0)} {Number(supplier.deliveryFee) > 0 ? ( Envio: ${Number(supplier.deliveryFee).toFixed(0)} ) : ( Envio gratis )}
); } function OrderCard({ order }: { order: any }) { const status = orderStatusConfig[order.status as keyof typeof orderStatusConfig] || orderStatusConfig.pending; const StatusIcon = status.icon; return (

Pedido #{order.orderNumber}

{status.label}

{order.supplier?.name}

{order.items?.length} productos

${Number(order.total).toLocaleString('es-MX', { minimumFractionDigits: 2 })}

{new Date(order.createdAt).toLocaleDateString('es-MX')}

); } function SupplierDetailModal({ supplier, onClose, onAddToCart, cart, }: { supplier: any; onClose: () => void; onAddToCart: (product: any) => void; cart: { product: any; quantity: number }[]; }) { const [search, setSearch] = useState(''); const queryClient = useQueryClient(); const { data: products = [], isLoading } = useQuery({ queryKey: ['supplier-products', supplier.id, search], queryFn: async () => { const response = await marketplaceApi.getSupplierProducts(supplier.id, { search: search || undefined, }); return response.data; }, }); const favoriteMutation = useMutation({ mutationFn: () => marketplaceApi.addFavorite(supplier.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['supplier-favorites'] }); }, }); const getCartQuantity = (productId: string) => { const item = cart.find((i) => i.product.id === productId); return item?.quantity || 0; }; return (
{/* Header */}
{supplier.logoUrl ? ( {supplier.name} ) : ( )}

{supplier.name}

{Number(supplier.rating).toFixed(1)} ยท {supplier.totalReviews} resenas
{supplier.address && (

{supplier.city}, {supplier.state}

)}
{supplier.contactPhone && ( Llamar )}
{/* Search */}
setSearch(e.target.value)} placeholder="Buscar productos..." className="input pl-10" />
{/* Products */}
{isLoading ? (
) : products.length === 0 ? (
No hay productos disponibles
) : (
{products.map((product: any) => { const inCart = getCartQuantity(product.id); return (
{product.imageUrl ? ( {product.name} ) : ( )}

{product.name}

Min: {product.minQuantity} {product.unitType}

${Number(product.unitPrice).toFixed(2)} {inCart > 0 ? ( {inCart} en carrito ) : ( )}
); })}
)}
); } function CartModal({ cart, supplier: _supplier, onClose, onUpdateQuantity, onRemove: _onRemove, onOrderSuccess, }: { cart: { product: any; quantity: number }[]; supplier: any; onClose: () => void; onUpdateQuantity: (productId: string, quantity: number) => void; onRemove: (productId: string) => void; onOrderSuccess: () => void; }) { const [deliveryAddress, setDeliveryAddress] = useState(''); const [deliveryPhone, setDeliveryPhone] = useState(''); const [notes, setNotes] = useState(''); const subtotal = cart.reduce( (sum, item) => sum + Number(item.product.unitPrice) * item.quantity, 0 ); const orderMutation = useMutation({ mutationFn: (data: any) => marketplaceApi.createOrder(data), onSuccess: onOrderSuccess, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const supplierId = cart[0]?.product?.supplierId; if (!supplierId) return; orderMutation.mutate({ supplierId, items: cart.map((item) => ({ productId: item.product.id, quantity: item.quantity, })), deliveryAddress, deliveryPhone, notes, }); }; return (

Tu Carrito

{/* Items */}
{cart.map((item) => (

{item.product.name}

${Number(item.product.unitPrice).toFixed(2)} x {item.quantity}

{item.quantity}

${(Number(item.product.unitPrice) * item.quantity).toFixed(2)}

))}
{/* Delivery Info */}

Datos de entrega