Implement Sirvoy booking services
This commit is contained in:
269
src/hooks/useChannelManager.ts
Normal file
269
src/hooks/useChannelManager.ts
Normal 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;
|
||||
Reference in New Issue
Block a user