diff options
Diffstat (limited to 'makima/frontend/src')
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveDetail.tsx | 28 | ||||
| -rw-r--r-- | makima/frontend/src/hooks/useDirectives.ts | 19 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 12 | ||||
| -rw-r--r-- | makima/frontend/src/routes/directives.tsx | 16 |
4 files changed, 67 insertions, 8 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx index 3634a79..e519b92 100644 --- a/makima/frontend/src/components/directives/DirectiveDetail.tsx +++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx @@ -8,6 +8,7 @@ interface DirectiveDetailProps { directive: DirectiveWithChains; onBack: () => void; onDelete?: (id: string) => void; + onStart?: (id: string) => void; } const statusColors: Record<DirectiveStatus, string> = { @@ -79,6 +80,7 @@ export function DirectiveDetail({ directive, onBack, onDelete, + onStart, }: DirectiveDetailProps) { return ( <div className="panel h-full flex flex-col"> @@ -101,14 +103,24 @@ export function DirectiveDetail({ <span className="font-mono text-[10px] text-[#7788aa]"> v{directive.version} </span> - {onDelete && ( - <button - onClick={() => onDelete(directive.id)} - className="ml-auto font-mono text-[10px] text-red-400 hover:text-red-300 transition-colors uppercase" - > - Delete - </button> - )} + <div className="ml-auto flex gap-2"> + {onStart && directive.status === "draft" && ( + <button + onClick={() => onStart(directive.id)} + className="font-mono text-[10px] text-green-400 hover:text-green-300 transition-colors uppercase" + > + Start + </button> + )} + {onDelete && ( + <button + onClick={() => onDelete(directive.id)} + className="font-mono text-[10px] text-red-400 hover:text-red-300 transition-colors uppercase" + > + Delete + </button> + )} + </div> </div> <h2 className="font-mono text-sm text-[#dbe7ff]"> {directive.title} diff --git a/makima/frontend/src/hooks/useDirectives.ts b/makima/frontend/src/hooks/useDirectives.ts index 001cf89..af1c8c6 100644 --- a/makima/frontend/src/hooks/useDirectives.ts +++ b/makima/frontend/src/hooks/useDirectives.ts @@ -5,6 +5,7 @@ import { createDirective, updateDirective, deleteDirective, + startDirective as startDirectiveApi, type DirectiveSummary, type DirectiveWithChains, type CreateDirectiveRequest, @@ -90,6 +91,23 @@ export function useDirectives() { [fetchDirectives] ); + const startDirective = useCallback( + async (id: string): Promise<boolean> => { + setError(null); + try { + await startDirectiveApi(id); + await fetchDirectives(); + return true; + } catch (e) { + setError( + e instanceof Error ? e.message : "Failed to start directive" + ); + return false; + } + }, + [fetchDirectives] + ); + // Initial fetch useEffect(() => { fetchDirectives(); @@ -104,5 +122,6 @@ export function useDirectives() { saveDirective, editDirective, removeDirective, + startDirective, }; } diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index 6c450eb..2187c34 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -3161,3 +3161,15 @@ export async function deleteDirective(id: string): Promise<void> { } } +export async function startDirective(id: string): Promise<Directive> { + const res = await authFetch(`${API_BASE}/api/v1/directives/${id}/start`, { + method: "POST", + }); + if (!res.ok) { + const body = await res.json().catch(() => null); + const msg = body?.message || res.statusText; + throw new Error(`Failed to start directive: ${msg}`); + } + return res.json(); +} + diff --git a/makima/frontend/src/routes/directives.tsx b/makima/frontend/src/routes/directives.tsx index 89535e2..8b82f99 100644 --- a/makima/frontend/src/routes/directives.tsx +++ b/makima/frontend/src/routes/directives.tsx @@ -50,6 +50,7 @@ function DirectivesContent() { fetchDirective, saveDirective, removeDirective, + startDirective, } = useDirectives(); const [selectedDirective, setSelectedDirective] = @@ -114,6 +115,20 @@ function DirectivesContent() { [removeDirective, id, navigate] ); + const handleStart = useCallback( + async (directiveId: string) => { + const ok = await startDirective(directiveId); + if (ok) { + // Refresh the detail view + const updated = await fetchDirective(directiveId); + if (updated) { + setSelectedDirective(updated); + } + } + }, + [startDirective, fetchDirective] + ); + // Detail view if (id) { if (detailLoading) { @@ -136,6 +151,7 @@ function DirectivesContent() { directive={selectedDirective} onBack={handleBack} onDelete={handleDelete} + onStart={handleStart} /> </main> ); |
