import React, { useState, useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Settings, Zap, TrendingUp, Calendar, Users, DollarSign, Plus, Search, MoreHorizontal, CheckCircle, AlertTriangle, XCircle, RefreshCw, Eye, Edit, Hotel, Utensils, Car, Plane, MapPin, Globe, BarChart3 } from 'lucide-react'; import { useChannelManager, Reservation } from '@/hooks/useChannelManager'; import { format } from 'date-fns'; import { es } from 'date-fns/locale'; import { ChannelConnectionModal } from '@/components/channel-manager/ChannelConnectionModal'; import { ListingFormModal } from '@/components/channel-manager/ListingFormModal'; import { ReservationDetailsModal } from '@/components/channel-manager/ReservationDetailsModal'; import { ReservationFormModal } from '@/components/channel-manager/ReservationFormModal'; import { ReservationsFilters } from '@/components/channel-manager/ReservationsFilters'; import { AnalyticsTab } from '@/components/channel-manager/AnalyticsTab'; import { useToast } from '@/hooks/use-toast'; const ChannelManager = () => { const location = useLocation(); const navigate = useNavigate(); const { toast } = useToast(); const { channels, listings, reservations, stats, loading, error, connectChannel, disconnectChannel, syncChannel, createListing, updateListing, createReservation, updateReservation, cancelReservation, loadStats, clearError } = useChannelManager(); // Get active tab from URL or default to 'overview' const queryParams = new URLSearchParams(location.search); const activeTab = queryParams.get('tab') || 'overview'; const [searchTerm, setSearchTerm] = useState(''); const [filterType, setFilterType] = useState('all'); const [showConnectModal, setShowConnectModal] = useState(false); const [showListingModal, setShowListingModal] = useState(false); const [showReservationModal, setShowReservationModal] = useState(false); const [showReservationForm, setShowReservationForm] = useState(false); const [reservationFormMode, setReservationFormMode] = useState<'create' | 'edit'>('create'); const [selectedReservation, setSelectedReservation] = useState(null); const [reservationFilters, setReservationFilters] = useState({ search: '', status: 'all', paymentStatus: 'all', channel: 'all', listingType: 'all', dateFrom: '', dateTo: '' }); const handleConnectChannel = async (data: any) => { const success = await connectChannel(data); if (success) { toast({ title: 'Canal conectado', description: 'El canal se ha conectado exitosamente', }); } else { toast({ title: 'Error', description: 'No se pudo conectar el canal', variant: 'destructive', }); } return success; }; const handleCreateListing = async (data: any) => { const success = await createListing(data); if (success) { toast({ title: 'Propiedad creada', description: 'La propiedad se ha creado exitosamente', }); } else { toast({ title: 'Error', description: 'No se pudo crear la propiedad', variant: 'destructive', }); } return success; }; const handleViewReservation = (reservation: Reservation) => { setSelectedReservation(reservation); setShowReservationModal(true); }; const handleCreateReservation = async (data: any) => { const success = await createReservation(data); if (success) { toast({ title: 'Reserva creada', description: 'La reserva se ha creado exitosamente', }); setShowReservationForm(false); } else { toast({ title: 'Error', description: 'No se pudo crear la reserva', variant: 'destructive', }); } return success; }; const handleUpdateReservation = async (data: any) => { if (!selectedReservation) return false; const success = await updateReservation(selectedReservation.id, data); if (success) { toast({ title: 'Reserva actualizada', description: 'La reserva se ha actualizado exitosamente', }); setShowReservationForm(false); setSelectedReservation(null); } else { toast({ title: 'Error', description: 'No se pudo actualizar la reserva', variant: 'destructive', }); } return success; }; const handleCancelReservation = async (id: string, reason?: string) => { const success = await cancelReservation(id, reason); if (success) { toast({ title: 'Reserva cancelada', description: 'La reserva se ha cancelado exitosamente', }); } else { toast({ title: 'Error', description: 'No se pudo cancelar la reserva', variant: 'destructive', }); } return success; }; const handleFilterChange = (key: string, value: string) => { setReservationFilters(prev => ({ ...prev, [key]: value })); }; const handleClearFilters = () => { setReservationFilters({ search: '', status: 'all', paymentStatus: 'all', channel: 'all', listingType: 'all', dateFrom: '', dateTo: '' }); }; const filteredReservations = reservations.filter(reservation => { if (reservationFilters.search && !reservation.guestName.toLowerCase().includes(reservationFilters.search.toLowerCase()) && !reservation.guestEmail.toLowerCase().includes(reservationFilters.search.toLowerCase()) && !reservation.id.toLowerCase().includes(reservationFilters.search.toLowerCase())) { return false; } if (reservationFilters.status !== 'all' && reservation.status !== reservationFilters.status) { return false; } if (reservationFilters.paymentStatus !== 'all' && reservation.paymentStatus !== reservationFilters.paymentStatus) { return false; } if (reservationFilters.channel !== 'all' && reservation.channel !== reservationFilters.channel) { return false; } if (reservationFilters.listingType !== 'all' && reservation.listingType !== reservationFilters.listingType) { return false; } if (reservationFilters.dateFrom && reservation.checkIn < reservationFilters.dateFrom) { return false; } if (reservationFilters.dateTo && reservation.checkIn > reservationFilters.dateTo) { return false; } return true; }); const getStatusIcon = (status: string) => { switch (status) { case 'connected': return ; case 'syncing': return ; case 'error': return ; default: return ; } }; const getTypeIcon = (type: string) => { switch (type) { case 'hotel': return ; case 'restaurant': return ; case 'vehicle': return ; case 'flight': return ; case 'activity': return ; default: return ; } }; const OverviewTab = () => (
{/* Key Metrics */}

Ingresos Totales

${stats?.totalRevenue.toLocaleString() || '0'}

Reservas Totales

{stats?.totalBookings || 0}

Tasa de Ocupación

{stats?.occupancyRate || 0}%

Canales Conectados

{channels.filter(c => c.status === 'connected').length}

{/* Channel Performance */} Rendimiento por Canal Ingresos y reservas por cada canal de distribución
{stats?.channelPerformance.map((channel, index) => (

{channel.channelName}

{channel.bookings} reservas

${channel.revenue.toLocaleString()}

Ingresos

))}
{/* Recent Reservations */} Reservas Recientes Últimas reservas recibidas en todos los canales
{reservations.slice(0, 5).map((reservation) => (
{getTypeIcon(reservation.listingType)}

{reservation.guestName}

{reservation.listingName}

{reservation.status}

${reservation.totalAmount.toLocaleString()}

))}
); const ChannelsTab = () => (

Gestión de Canales

Conecta y administra tus canales de distribución

{channels.length === 0 ? (

No hay canales conectados

Conecta tu primer canal de distribución para comenzar a sincronizar reservas

) : (
{channels.map((channel) => (

{channel.name}

{getStatusIcon(channel.status)} {channel.type}

Última sincronización: {format(new Date(channel.lastSync), 'dd/MM/yyyy HH:mm', { locale: es })}

{channel.properties.length} propiedades conectadas

${channel.revenue.toLocaleString()}

{channel.bookings} reservas

Comisión: {channel.commission}%

))}
)}
); const ListingsTab = () => { const filteredListings = listings.filter(listing => { const matchesSearch = listing.name.toLowerCase().includes(searchTerm.toLowerCase()); const matchesType = filterType === 'all' || listing.type === filterType; return matchesSearch && matchesType; }); return (

Gestión de Propiedades

Administra hoteles, restaurantes, vehículos y más

setSearchTerm(e.target.value)} className="pl-10" />
{filteredListings.map((listing) => (
{listing.images[0] ? ( {listing.name} ) : ( getTypeIcon(listing.type) )}

{listing.name}

{listing.status} {listing.type}

{listing.location.address}

Conectado a {listing.channels.length} canales

${listing.basePrice}

{listing.availability ? 'Disponible' : 'No disponible'}

))}
); }; const ReservationsTab = () => (

Gestión de Reservas

Administra todas las reservas desde un solo lugar

{filteredReservations.length === 0 ? (

No se encontraron reservas

{reservations.length === 0 ? 'Aún no hay reservas registradas. Crea tu primera reserva para comenzar.' : 'Intenta ajustar los filtros para ver más resultados.'}

{reservations.length === 0 && ( )}
) : ( <>
{filteredReservations.map((reservation) => (
{getTypeIcon(reservation.listingType)}

{reservation.guestName}

{reservation.status}

{reservation.listingName}

{format(new Date(reservation.checkIn), 'dd/MM/yyyy', { locale: es })} {reservation.checkOut && ` - ${format(new Date(reservation.checkOut), 'dd/MM/yyyy', { locale: es })}`}

{reservation.guests} huéspedes • {reservation.channel}

${reservation.totalAmount.toLocaleString()}

Pago: {reservation.paymentStatus}

))}
Mostrando {filteredReservations.length} de {reservations.length} reservas
)}
); return (

Channel Manager

Gestiona todos tus canales de distribución, propiedades y reservas desde un solo lugar

{activeTab === 'overview' && } {activeTab === 'channels' && } {activeTab === 'listings' && } {activeTab === 'reservations' && } {activeTab === 'analytics' && } {/* Modals */} setShowConnectModal(false)} onConnect={handleConnectChannel} /> setShowListingModal(false)} onCreate={handleCreateListing} onUpdate={updateListing} channels={channels} /> { setShowReservationModal(false); setSelectedReservation(null); }} reservation={selectedReservation} onCancel={handleCancelReservation} /> { setShowReservationForm(false); setSelectedReservation(null); }} onSubmit={reservationFormMode === 'create' ? handleCreateReservation : handleUpdateReservation} reservation={selectedReservation} listings={listings} mode={reservationFormMode} />
); }; export default ChannelManager;