import { useCallback, useState } from "react"; import { getBookingActions, getNextPendingApprovalStep, type BookingActionContext, type BookingActionDef, } from "@/features/bookings/booking-actions.config"; import { useAuth } from "@/auth/useAuth"; import { useBookingDetail, useBookingMutations } from "@/hooks/bookings/useBookings"; export function useBookingActionDialog( bookingId: string, context: BookingActionContext, ) { const [pendingAction, setPendingAction] = useState(null); const [inputValue, setInputValue] = useState(""); const [selectedFile, setSelectedFile] = useState(null); const [dialogOpen, setDialogOpen] = useState(false); const needsApprovalSteps = pendingAction?.id === "approve" || pendingAction?.id === "rejectApproval"; const needsApprovalContext = context.status === "PENDING_APPROVAL" || context.status === "APPROVED_PENDING_SIGNATURE"; const { data: detail, isLoading: detailLoading } = useBookingDetail( needsApprovalSteps || needsApprovalContext ? bookingId : undefined, ); const mergedContext: BookingActionContext = { ...context, approvalSteps: detail?.approvalSteps ?? context.approvalSteps, reference: detail?.reference ?? context.reference, }; const { user } = useAuth(); const mutations = useBookingMutations(bookingId); const actions = getBookingActions(mergedContext, user); const openAction = useCallback((action: BookingActionDef) => { setPendingAction(action); setInputValue(""); setSelectedFile(null); setDialogOpen(true); }, []); const closeDialog = useCallback(() => { setDialogOpen(false); setPendingAction(null); setInputValue(""); setSelectedFile(null); }, []); const runAction = useCallback(() => { if (!pendingAction) return; const onSuccess = () => closeDialog(); switch (pendingAction.id) { case "accept": mutations.staffAccept.mutate(undefined, { onSuccess }); break; case "requestChanges": mutations.requestChanges.mutate(inputValue.trim(), { onSuccess }); break; case "reject": mutations.staffReject.mutate(inputValue.trim(), { onSuccess }); break; case "approve": { const step = getNextPendingApprovalStep(mergedContext.approvalSteps); if (!step) return; mutations.approveStep.mutate( { stepId: step.id, requiredRole: step.requiredRole }, { onSuccess }, ); break; } case "rejectApproval": { const step = getNextPendingApprovalStep(mergedContext.approvalSteps); if (!step) return; mutations.rejectStep.mutate( { stepId: step.id, reason: inputValue.trim() }, { onSuccess }, ); break; } case "viewContract": break; case "startTransit": mutations.startTransit.mutate(undefined, { onSuccess }); break; case "complete": mutations.complete.mutate(undefined, { onSuccess }); break; case "cancel": mutations.cancel.mutate(inputValue.trim(), { onSuccess }); break; default: break; } }, [ pendingAction, inputValue, selectedFile, mergedContext.approvalSteps, mutations, closeDialog, ]); const confirmDisabled = mutations.isPending || (needsApprovalSteps && detailLoading) || (pendingAction?.id === "approve" && !getNextPendingApprovalStep(mergedContext.approvalSteps)) || (pendingAction?.input === "file" && !selectedFile) || (pendingAction?.input === "reason" && !inputValue.trim()) || (pendingAction?.input === "note" && !inputValue.trim()); return { actions, pendingAction, inputValue, setInputValue, selectedFile, setSelectedFile, dialogOpen, setDialogOpen: (open: boolean) => { if (!open) closeDialog(); else setDialogOpen(true); }, openAction, closeDialog, runAction, mutations, confirmDisabled, detailLoading, mergedContext, }; }