Implement Sirvoy booking services

This commit is contained in:
gpt-engineer-app[bot]
2025-09-25 18:25:37 +00:00
parent 557f8bdd77
commit 576d7dd711
5 changed files with 998 additions and 4 deletions

View File

@@ -0,0 +1,269 @@
import { useState, useEffect, useCallback } from 'react';
import { ChannelManagerService } from '@/services/channelManagerApi';
export interface Channel {
id: string;
name: string;
type: 'booking.com' | 'expedia' | 'airbnb' | 'vrbo' | 'agoda' | 'direct' | 'other';
status: 'connected' | 'disconnected' | 'syncing' | 'error';
lastSync: string;
properties: string[];
revenue: number;
bookings: number;
commission: number;
}
export interface Listing {
id: string;
name: string;
type: 'hotel' | 'restaurant' | 'vehicle' | 'flight' | 'activity';
status: 'active' | 'inactive' | 'draft';
channels: string[];
basePrice: number;
availability: boolean;
images: string[];
description: string;
location: {
address: string;
coordinates: { lat: number; lng: number };
};
createdAt: string;
updatedAt: string;
}
export interface Reservation {
id: string;
listingId: string;
listingName: string;
listingType: 'hotel' | 'restaurant' | 'vehicle' | 'flight' | 'activity';
guestName: string;
guestEmail: string;
guestPhone: string;
checkIn: string;
checkOut?: string;
guests: number;
totalAmount: number;
status: 'confirmed' | 'pending' | 'cancelled' | 'completed';
paymentStatus: 'paid' | 'pending' | 'refunded';
channel: string;
specialRequests?: string;
createdAt: string;
}
export interface ChannelManagerStats {
totalRevenue: number;
totalBookings: number;
occupancyRate: number;
averageRate: number;
channelPerformance: {
channelName: string;
revenue: number;
bookings: number;
}[];
}
export const useChannelManager = () => {
const [channels, setChannels] = useState<Channel[]>([]);
const [listings, setListings] = useState<Listing[]>([]);
const [reservations, setReservations] = useState<Reservation[]>([]);
const [stats, setStats] = useState<ChannelManagerStats | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Load channels
const loadChannels = useCallback(async () => {
try {
setLoading(true);
const data = await ChannelManagerService.getChannels();
setChannels(data || []);
} catch (err) {
setError(err instanceof Error ? err.message : 'Error loading channels');
} finally {
setLoading(false);
}
}, []);
// Load listings
const loadListings = useCallback(async (type?: string) => {
try {
setLoading(true);
const data = await ChannelManagerService.getListings(type);
setListings(data || []);
} catch (err) {
setError(err instanceof Error ? err.message : 'Error loading listings');
} finally {
setLoading(false);
}
}, []);
// Load reservations
const loadReservations = useCallback(async (filters?: any) => {
try {
setLoading(true);
const data = await ChannelManagerService.getReservations(filters);
setReservations(data || []);
} catch (err) {
setError(err instanceof Error ? err.message : 'Error loading reservations');
} finally {
setLoading(false);
}
}, []);
// Load analytics
const loadStats = useCallback(async (dateRange: { startDate: string; endDate: string }) => {
try {
setLoading(true);
const [revenueData, channelData] = await Promise.all([
ChannelManagerService.getRevenueReports(dateRange),
ChannelManagerService.getChannelPerformance()
]);
setStats({
totalRevenue: revenueData?.totalRevenue || 0,
totalBookings: revenueData?.totalBookings || 0,
occupancyRate: revenueData?.occupancyRate || 0,
averageRate: revenueData?.averageRate || 0,
channelPerformance: channelData || []
});
} catch (err) {
setError(err instanceof Error ? err.message : 'Error loading statistics');
} finally {
setLoading(false);
}
}, []);
// Connect new channel
const connectChannel = useCallback(async (channelData: any) => {
try {
setLoading(true);
await ChannelManagerService.connectChannel(channelData);
await loadChannels(); // Reload channels after connecting
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error connecting channel');
return false;
} finally {
setLoading(false);
}
}, [loadChannels]);
// Disconnect channel
const disconnectChannel = useCallback(async (channelId: string) => {
try {
setLoading(true);
await ChannelManagerService.disconnectChannel(channelId);
await loadChannels(); // Reload channels after disconnecting
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error disconnecting channel');
return false;
} finally {
setLoading(false);
}
}, [loadChannels]);
// Sync channel
const syncChannel = useCallback(async (channelId: string) => {
try {
setLoading(true);
await ChannelManagerService.syncChannel(channelId);
await loadChannels(); // Reload channels after syncing
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error syncing channel');
return false;
} finally {
setLoading(false);
}
}, [loadChannels]);
// Create listing
const createListing = useCallback(async (listingData: any) => {
try {
setLoading(true);
await ChannelManagerService.createListing(listingData);
await loadListings(); // Reload listings after creating
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error creating listing');
return false;
} finally {
setLoading(false);
}
}, [loadListings]);
// Update listing
const updateListing = useCallback(async (id: string, listingData: any) => {
try {
setLoading(true);
await ChannelManagerService.updateListing(id, listingData);
await loadListings(); // Reload listings after updating
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error updating listing');
return false;
} finally {
setLoading(false);
}
}, [loadListings]);
// Cancel reservation
const cancelReservation = useCallback(async (id: string, reason?: string) => {
try {
setLoading(true);
await ChannelManagerService.cancelReservation(id, reason);
await loadReservations(); // Reload reservations after cancelling
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Error cancelling reservation');
return false;
} finally {
setLoading(false);
}
}, [loadReservations]);
// Clear error
const clearError = useCallback(() => {
setError(null);
}, []);
// Load initial data
useEffect(() => {
loadChannels();
loadListings();
loadReservations();
const dateRange = {
startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
endDate: new Date().toISOString().split('T')[0]
};
loadStats(dateRange);
}, [loadChannels, loadListings, loadReservations, loadStats]);
return {
// Data
channels,
listings,
reservations,
stats,
// States
loading,
error,
// Actions
loadChannels,
loadListings,
loadReservations,
loadStats,
connectChannel,
disconnectChannel,
syncChannel,
createListing,
updateListing,
cancelReservation,
clearError,
};
};
export default useChannelManager;