summaryrefslogtreecommitdiff
path: root/makima/frontend/src/hooks
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-03 22:01:29 +0000
committersoryu <soryu@soryu.co>2026-02-03 22:01:37 +0000
commitcf0a25af1d2834bfe6c5ea892ce5769936e5a673 (patch)
tree476ba326ac1752281a441b5c17d2b3be4b23a2a9 /makima/frontend/src/hooks
parent8361916ce67f3d2ba191ebf27cb50e79cb42e39c (diff)
downloadsoryu-cf0a25af1d2834bfe6c5ea892ce5769936e5a673.tar.gz
soryu-cf0a25af1d2834bfe6c5ea892ce5769936e5a673.zip
Add makima chain mechanism
Diffstat (limited to 'makima/frontend/src/hooks')
-rw-r--r--makima/frontend/src/hooks/useChains.ts145
1 files changed, 145 insertions, 0 deletions
diff --git a/makima/frontend/src/hooks/useChains.ts b/makima/frontend/src/hooks/useChains.ts
new file mode 100644
index 0000000..272847a
--- /dev/null
+++ b/makima/frontend/src/hooks/useChains.ts
@@ -0,0 +1,145 @@
+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,
+ };
+}