Files
stackpilot/frontend/src/hooks/useStackActions.ts
T
menzeljandClaude Opus 4.8 f732cb080b Initial commit: StackPilot Phase 1 (Core)
Self-hosted Docker Compose manager.
- Backend: FastAPI + docker-py + SQLite (JWT auth, file-first stacks,
  lifecycle, live status, WebSocket logs, docker-run converter, audit log)
- Frontend: React + Vite + Tailwind (login/setup, dashboard, stacks,
  stack detail, Monaco editor, dark/light theme)
- Deployment: docker-compose.yml, Dockerfiles, nginx reverse proxy

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 16:04:58 +00:00

40 lines
1.2 KiB
TypeScript

import { useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { stacksApi } from "@/api/stacks";
import { apiErrorMessage } from "@/api/client";
export function useStackActions() {
const qc = useQueryClient();
const [busyId, setBusyId] = useState<string | null>(null);
const run = async (
id: string,
label: string,
fn: (id: string) => Promise<unknown>
) => {
setBusyId(id);
const t = toast.loading(`${label} ${id}…`);
try {
await fn(id);
toast.success(`${label} ${id} ✓`, { id: t });
qc.invalidateQueries({ queryKey: ["stacks"] });
qc.invalidateQueries({ queryKey: ["stack", id] });
} catch (err) {
toast.error(apiErrorMessage(err), { id: t });
} finally {
setBusyId(null);
}
};
return {
busyId,
start: (id: string) => run(id, "Starting", stacksApi.start),
stop: (id: string) => run(id, "Stopping", stacksApi.stop),
restart: (id: string) => run(id, "Restarting", stacksApi.restart),
pull: (id: string) => run(id, "Pulling", stacksApi.pull),
updateImages: (id: string) => run(id, "Updating", stacksApi.update_images),
down: (id: string) => run(id, "Tearing down", stacksApi.down),
};
}