"use client"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useCallback } from "react"; import { createAppointment, getAvailableDates, listAppointments, getUserAppointments, getAppointmentDetail, scheduleAppointment, rejectAppointment, getAdminAvailability, updateAdminAvailability, getAppointmentStats, getJitsiMeetingInfo, } from "@/lib/actions/appointments"; import type { CreateAppointmentInput, ScheduleAppointmentInput, RejectAppointmentInput, UpdateAvailabilityInput, } from "@/lib/schema/appointments"; import type { Appointment, AdminAvailability, AppointmentStats, JitsiMeetingInfo, } from "@/lib/models/appointments"; export function useAppointments() { const queryClient = useQueryClient(); // Get available dates query const availableDatesQuery = useQuery({ queryKey: ["appointments", "available-dates"], queryFn: () => getAvailableDates(), staleTime: 5 * 60 * 1000, // 5 minutes }); // List appointments query const appointmentsQuery = useQuery({ queryKey: ["appointments", "list"], queryFn: () => listAppointments(), enabled: false, // Only fetch when explicitly called }); // Get user appointments query const userAppointmentsQuery = useQuery({ queryKey: ["appointments", "user"], queryFn: () => getUserAppointments(), staleTime: 30 * 1000, // 30 seconds }); // Get appointment detail query const useAppointmentDetail = (id: string | null) => { return useQuery({ queryKey: ["appointments", "detail", id], queryFn: () => getAppointmentDetail(id!), enabled: !!id, }); }; // Get admin availability query const adminAvailabilityQuery = useQuery({ queryKey: ["appointments", "admin", "availability"], queryFn: () => getAdminAvailability(), staleTime: 5 * 60 * 1000, // 5 minutes }); // Get appointment stats query const appointmentStatsQuery = useQuery({ queryKey: ["appointments", "stats"], queryFn: () => getAppointmentStats(), staleTime: 1 * 60 * 1000, // 1 minute }); // Get user appointment stats query const userAppointmentStatsQuery = useQuery({ queryKey: ["appointments", "user", "stats"], queryFn: () => getUserAppointmentStats(), staleTime: 1 * 60 * 1000, // 1 minute }); // Get Jitsi meeting info query const useJitsiMeetingInfo = (id: string | null) => { return useQuery({ queryKey: ["appointments", "jitsi", id], queryFn: () => getJitsiMeetingInfo(id!), enabled: !!id, staleTime: 30 * 1000, // 30 seconds }); }; // Create appointment mutation const createAppointmentMutation = useMutation({ mutationFn: (input: CreateAppointmentInput) => createAppointment(input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["appointments"] }); }, }); // Schedule appointment mutation const scheduleAppointmentMutation = useMutation({ mutationFn: ({ id, input }: { id: string; input: ScheduleAppointmentInput }) => scheduleAppointment(id, input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["appointments"] }); }, }); // Reject appointment mutation const rejectAppointmentMutation = useMutation({ mutationFn: ({ id, input }: { id: string; input: RejectAppointmentInput }) => rejectAppointment(id, input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["appointments"] }); }, }); // Update admin availability mutation const updateAdminAvailabilityMutation = useMutation({ mutationFn: (input: UpdateAvailabilityInput) => updateAdminAvailability(input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["appointments", "admin", "availability"] }); queryClient.invalidateQueries({ queryKey: ["appointments", "available-dates"] }); }, }); // Convenience functions const create = useCallback( async (input: CreateAppointmentInput) => { return await createAppointmentMutation.mutateAsync(input); }, [createAppointmentMutation] ); const schedule = useCallback( async (id: string, input: ScheduleAppointmentInput) => { return await scheduleAppointmentMutation.mutateAsync({ id, input }); }, [scheduleAppointmentMutation] ); const reject = useCallback( async (id: string, input: RejectAppointmentInput) => { return await rejectAppointmentMutation.mutateAsync({ id, input }); }, [rejectAppointmentMutation] ); const updateAvailability = useCallback( async (input: UpdateAvailabilityInput) => { return await updateAdminAvailabilityMutation.mutateAsync(input); }, [updateAdminAvailabilityMutation] ); const fetchAppointments = useCallback( async (email?: string) => { const data = await listAppointments(email); queryClient.setQueryData(["appointments", "list"], data); return data; }, [queryClient] ); return { // Queries availableDates: availableDatesQuery.data?.dates || [], availableDatesResponse: availableDatesQuery.data, appointments: appointmentsQuery.data || [], userAppointments: userAppointmentsQuery.data || [], adminAvailability: adminAvailabilityQuery.data, appointmentStats: appointmentStatsQuery.data, userAppointmentStats: userAppointmentStatsQuery.data, // Query states isLoadingAvailableDates: availableDatesQuery.isLoading, isLoadingAppointments: appointmentsQuery.isLoading, isLoadingUserAppointments: userAppointmentsQuery.isLoading, isLoadingAdminAvailability: adminAvailabilityQuery.isLoading, isLoadingStats: appointmentStatsQuery.isLoading, isLoadingUserStats: userAppointmentStatsQuery.isLoading, // Query refetch functions refetchAvailableDates: availableDatesQuery.refetch, refetchAppointments: appointmentsQuery.refetch, refetchUserAppointments: userAppointmentsQuery.refetch, refetchAdminAvailability: adminAvailabilityQuery.refetch, refetchStats: appointmentStatsQuery.refetch, refetchUserStats: userAppointmentStatsQuery.refetch, // Hooks for specific queries useAppointmentDetail, useJitsiMeetingInfo, // Mutations create, schedule, reject, updateAvailability, fetchAppointments, // Mutation states isCreating: createAppointmentMutation.isPending, isScheduling: scheduleAppointmentMutation.isPending, isRejecting: rejectAppointmentMutation.isPending, isUpdatingAvailability: updateAdminAvailabilityMutation.isPending, // Direct mutation access (if needed) createAppointmentMutation, scheduleAppointmentMutation, rejectAppointmentMutation, updateAdminAvailabilityMutation, }; }