Initial commit: monorepo Naturcalabacera reservas (apps/api + apps/web + packages/shared)
This commit is contained in:
103
apps/web/src/hooks/useReservations.ts
Normal file
103
apps/web/src/hooks/useReservations.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { supabase } from '../lib/supabase';
|
||||
import type { Reservation, NewReservation, Property } from '../types';
|
||||
|
||||
export function useReservations(property: Property) {
|
||||
const [reservations, setReservations] = useState<Reservation[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchReservations = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { data, error } = await supabase
|
||||
.from('reservations')
|
||||
.select('*')
|
||||
.eq('property', property)
|
||||
.order('start_date', { ascending: true });
|
||||
|
||||
if (error) throw error;
|
||||
setReservations(data || []);
|
||||
} catch (err: unknown) {
|
||||
setError(err instanceof Error ? err.message : 'Error desconocido');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchReservations();
|
||||
|
||||
// Suscripción realtime filtrada por propiedad
|
||||
const channel = supabase
|
||||
.channel(`reservations_${property}`)
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: '*',
|
||||
schema: 'natur_reservas',
|
||||
table: 'reservations',
|
||||
filter: `property=eq.${property}`,
|
||||
},
|
||||
() => {
|
||||
fetchReservations();
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
supabase.removeChannel(channel);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [property]);
|
||||
|
||||
const createReservation = async (reservation: NewReservation): Promise<Reservation> => {
|
||||
const { data: authData } = await supabase.auth.getUser();
|
||||
const payload = {
|
||||
...reservation,
|
||||
property,
|
||||
created_by: authData.user?.id,
|
||||
};
|
||||
const { data, error } = await supabase
|
||||
.from('reservations')
|
||||
.insert([payload])
|
||||
.select('id')
|
||||
.single();
|
||||
if (error) throw error;
|
||||
const { data: created, error: fetchError } = await supabase
|
||||
.from('reservations')
|
||||
.select('*')
|
||||
.eq('id', data.id)
|
||||
.single();
|
||||
if (fetchError) throw fetchError;
|
||||
return created as Reservation;
|
||||
};
|
||||
|
||||
const updateReservation = async (id: string, updates: Partial<Reservation>) => {
|
||||
const { data: authData } = await supabase.auth.getUser();
|
||||
const payload = {
|
||||
...updates,
|
||||
updated_by: authData.user?.id,
|
||||
};
|
||||
const { error } = await supabase
|
||||
.from('reservations')
|
||||
.update(payload)
|
||||
.eq('id', id);
|
||||
if (error) throw error;
|
||||
};
|
||||
|
||||
const deleteReservation = async (id: string) => {
|
||||
const { error } = await supabase.from('reservations').delete().eq('id', id);
|
||||
if (error) throw error;
|
||||
};
|
||||
|
||||
return {
|
||||
reservations,
|
||||
loading,
|
||||
error,
|
||||
createReservation,
|
||||
updateReservation,
|
||||
deleteReservation,
|
||||
refreshResolver: fetchReservations,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user