Files
kandev/apps/web/components/settings/use-agent-update-dialog-state.ts
T
2026-07-27 19:34:13 +01:00

95 lines
2.7 KiB
TypeScript

"use client";
import { useCallback, useEffect, useRef, useState } from "react";
import type { AgentUpdateJob, AgentUpdatePreview } from "@/lib/api";
function errorMessage(error: unknown) {
return error instanceof Error ? error.message : String(error);
}
type UseAgentUpdateDialogStateOptions = {
agentName: string;
job?: AgentUpdateJob;
onPreview: (agentName: string) => Promise<AgentUpdatePreview>;
onUpdate: (agentName: string) => Promise<AgentUpdateJob>;
};
export function useAgentUpdateDialogState({
agentName,
job,
onPreview,
onUpdate,
}: UseAgentUpdateDialogStateOptions) {
const [open, setOpen] = useState(false);
const [preview, setPreview] = useState<AgentUpdatePreview | null>(null);
const [previewError, setPreviewError] = useState<string | null>(null);
const [approveError, setApproveError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const [starting, setStarting] = useState(false);
const [activeJobID, setActiveJobID] = useState<string | null>(null);
const previewRequestID = useRef(0);
const activeJob = activeJobID === job?.job_id ? job : undefined;
const reset = useCallback(() => {
previewRequestID.current += 1;
setPreview(null);
setPreviewError(null);
setApproveError(null);
setLoading(false);
setStarting(false);
setActiveJobID(null);
}, []);
const loadPreview = useCallback(async () => {
const requestID = ++previewRequestID.current;
setLoading(true);
setPreview(null);
setPreviewError(null);
setApproveError(null);
try {
const nextPreview = await onPreview(agentName);
if (requestID === previewRequestID.current) setPreview(nextPreview);
} catch (error) {
if (requestID === previewRequestID.current) setPreviewError(errorMessage(error));
} finally {
if (requestID === previewRequestID.current) setLoading(false);
}
}, [agentName, onPreview]);
useEffect(() => {
if (open) void loadPreview();
}, [loadPreview, open]);
const handleOpenChange = (nextOpen: boolean) => {
setOpen(nextOpen);
if (!nextOpen) reset();
};
const approve = async () => {
const requestID = previewRequestID.current;
setStarting(true);
setApproveError(null);
try {
const nextJob = await onUpdate(agentName);
if (requestID === previewRequestID.current) setActiveJobID(nextJob.job_id);
} catch (error) {
if (requestID === previewRequestID.current) setApproveError(errorMessage(error));
} finally {
if (requestID === previewRequestID.current) setStarting(false);
}
};
return {
activeJob,
approve,
approveError,
handleOpenChange,
loading,
loadPreview,
open,
preview,
previewError,
starting,
};
}