import { useState, useCallback, useEffect } from "react";
import {
listChains,
getChain,
createChain,
updateChain,
archiveChain,
getChainGraph,
type ChainSummary,
type ChainWithContracts,
type ChainGraphResponse,
type ChainStatus,
type CreateChainRequest,
type UpdateChainRequest,
} from "../lib/api";
interface UseChainsResult {
chains: ChainSummary[];
loading: boolean;
error: string | null;
refresh: () => Promise<void>;
createNewChain: (req: CreateChainRequest) => Promise<ChainWithContracts | null>;
updateExistingChain: (
chainId: string,
req: UpdateChainRequest
) => Promise<ChainWithContracts | null>;
archiveExistingChain: (chainId: string) => Promise<boolean>;
getChainById: (chainId: string) => Promise<ChainWithContracts | null>;
getGraph: (chainId: string) => Promise<ChainGraphResponse | null>;
}
export function useChains(statusFilter?: ChainStatus): UseChainsResult {
const [chains, setChains] = useState<ChainSummary[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchChains = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await listChains(statusFilter);
setChains(response.chains);
} catch (err) {
console.error("Failed to fetch chains:", err);
setError(err instanceof Error ? err.message : "Failed to fetch chains");
} finally {
setLoading(false);
}
}, [statusFilter]);
useEffect(() => {
fetchChains();
}, [fetchChains]);
const createNewChain = useCallback(
async (req: CreateChainRequest): Promise<ChainWithContracts | null> => {
try {
const chain = await createChain(req);
// Refresh the list
await fetchChains();
// Return the full chain with contracts
return await getChain(chain.id);
} catch (err) {
console.error("Failed to create chain:", err);
setError(err instanceof Error ? err.message : "Failed to create chain");
return null;
}
},
[fetchChains]
);
const updateExistingChain = useCallback(
async (
chainId: string,
req: UpdateChainRequest
): Promise<ChainWithContracts | null> => {
try {
await updateChain(chainId, req);
// Refresh the list
await fetchChains();
// Return the updated chain
return await getChain(chainId);
} catch (err) {
console.error("Failed to update chain:", err);
setError(err instanceof Error ? err.message : "Failed to update chain");
return null;
}
},
[fetchChains]
);
const archiveExistingChain = useCallback(
async (chainId: string): Promise<boolean> => {
try {
await archiveChain(chainId);
// Refresh the list
await fetchChains();
return true;
} catch (err) {
console.error("Failed to archive chain:", err);
setError(err instanceof Error ? err.message : "Failed to archive chain");
return false;
}
},
[fetchChains]
);
const getChainById = useCallback(
async (chainId: string): Promise<ChainWithContracts | null> => {
try {
return await getChain(chainId);
} catch (err) {
console.error("Failed to get chain:", err);
setError(err instanceof Error ? err.message : "Failed to get chain");
return null;
}
},
[]
);
const getGraph = useCallback(
async (chainId: string): Promise<ChainGraphResponse | null> => {
try {
return await getChainGraph(chainId);
} catch (err) {
console.error("Failed to get chain graph:", err);
setError(err instanceof Error ? err.message : "Failed to get chain graph");
return null;
}
},
[]
);
return {
chains,
loading,
error,
refresh: fetchChains,
createNewChain,
updateExistingChain,
archiveExistingChain,
getChainById,
getGraph,
};
}