summaryrefslogtreecommitdiff
path: root/makima/frontend/src/hooks
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-09 00:11:51 +0000
committersoryu <soryu@soryu.co>2026-02-09 00:11:51 +0000
commit8c23b3ab6f7fabca01b0468911bae073aa5ced32 (patch)
treef50159aee13b13f0b55618ac09e9be1f89a41bb2 /makima/frontend/src/hooks
parent3662b334dfd68cfdf00ed44ae88927c2e1b2aabe (diff)
downloadsoryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.tar.gz
soryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.zip
Add new directive mechanism v3
Diffstat (limited to 'makima/frontend/src/hooks')
-rw-r--r--makima/frontend/src/hooks/useDirectives.ts150
1 files changed, 150 insertions, 0 deletions
diff --git a/makima/frontend/src/hooks/useDirectives.ts b/makima/frontend/src/hooks/useDirectives.ts
new file mode 100644
index 0000000..b69275a
--- /dev/null
+++ b/makima/frontend/src/hooks/useDirectives.ts
@@ -0,0 +1,150 @@
+import { useState, useEffect, useCallback } from "react";
+import {
+ type DirectiveSummary,
+ type DirectiveWithSteps,
+ type CreateDirectiveRequest,
+ type UpdateDirectiveRequest,
+ type CreateDirectiveStepRequest,
+ listDirectives,
+ createDirective,
+ getDirective,
+ updateDirective,
+ deleteDirective,
+ createDirectiveStep,
+ deleteDirectiveStep,
+ startDirective,
+ pauseDirective,
+ advanceDirective,
+ completeDirectiveStep,
+ failDirectiveStep,
+ skipDirectiveStep,
+ updateDirectiveGoal,
+} from "../lib/api";
+
+export function useDirectives() {
+ const [directives, setDirectives] = useState<DirectiveSummary[]>([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState<string | null>(null);
+
+ const refresh = useCallback(async () => {
+ try {
+ setLoading(true);
+ setError(null);
+ const res = await listDirectives();
+ setDirectives(res.directives);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Failed to load directives");
+ } finally {
+ setLoading(false);
+ }
+ }, []);
+
+ useEffect(() => {
+ refresh();
+ }, [refresh]);
+
+ const create = useCallback(async (req: CreateDirectiveRequest) => {
+ const d = await createDirective(req);
+ await refresh();
+ return d;
+ }, [refresh]);
+
+ const remove = useCallback(async (id: string) => {
+ await deleteDirective(id);
+ await refresh();
+ }, [refresh]);
+
+ return { directives, loading, error, refresh, create, remove };
+}
+
+export function useDirective(id: string | undefined) {
+ const [directive, setDirective] = useState<DirectiveWithSteps | null>(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState<string | null>(null);
+
+ const refresh = useCallback(async () => {
+ if (!id) return;
+ try {
+ setLoading(true);
+ setError(null);
+ const d = await getDirective(id);
+ setDirective(d);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "Failed to load directive");
+ } finally {
+ setLoading(false);
+ }
+ }, [id]);
+
+ useEffect(() => {
+ refresh();
+ }, [refresh]);
+
+ const update = useCallback(async (req: UpdateDirectiveRequest) => {
+ if (!id) return;
+ await updateDirective(id, req);
+ await refresh();
+ }, [id, refresh]);
+
+ const addStep = useCallback(async (req: CreateDirectiveStepRequest) => {
+ if (!id) return;
+ await createDirectiveStep(id, req);
+ await refresh();
+ }, [id, refresh]);
+
+ const removeStep = useCallback(async (stepId: string) => {
+ if (!id) return;
+ await deleteDirectiveStep(id, stepId);
+ await refresh();
+ }, [id, refresh]);
+
+ const start = useCallback(async () => {
+ if (!id) return;
+ await startDirective(id);
+ await refresh();
+ }, [id, refresh]);
+
+ const pause = useCallback(async () => {
+ if (!id) return;
+ await pauseDirective(id);
+ await refresh();
+ }, [id, refresh]);
+
+ const advance = useCallback(async () => {
+ if (!id) return;
+ await advanceDirective(id);
+ await refresh();
+ }, [id, refresh]);
+
+ const completeStep = useCallback(async (stepId: string) => {
+ if (!id) return;
+ await completeDirectiveStep(id, stepId);
+ await refresh();
+ }, [id, refresh]);
+
+ const failStep = useCallback(async (stepId: string) => {
+ if (!id) return;
+ await failDirectiveStep(id, stepId);
+ await refresh();
+ }, [id, refresh]);
+
+ const skipStep = useCallback(async (stepId: string) => {
+ if (!id) return;
+ await skipDirectiveStep(id, stepId);
+ await refresh();
+ }, [id, refresh]);
+
+ const updateGoal = useCallback(async (goal: string) => {
+ if (!id) return;
+ await updateDirectiveGoal(id, goal);
+ await refresh();
+ }, [id, refresh]);
+
+ return {
+ directive, loading, error, refresh,
+ update, addStep, removeStep,
+ start, pause, advance,
+ completeStep, failStep, skipStep,
+ updateGoal,
+ };
+}