Pipeline/frontend/src/components/git/CloseForgejoIssueDialog.tsx

101 lines
2.9 KiB
TypeScript

"use client";
import { useState } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import type { ForgejoIssue } from "@/lib/api-forgejo";
import { closeForgejoIssue } from "@/lib/api-forgejo";
type CloseForgejoIssueDialogProps = {
issue: ForgejoIssue | null;
open: boolean;
onOpenChange: (open: boolean) => void;
onCloseSuccess: () => void;
};
export function CloseForgejoIssueDialog({
issue,
open,
onOpenChange,
onCloseSuccess,
}: CloseForgejoIssueDialogProps) {
const [isClosing, setIsClosing] = useState(false);
const [error, setError] = useState<string | null>(null);
if (!issue) return null;
const handleClose = async () => {
setIsClosing(true);
setError(null);
try {
await closeForgejoIssue(issue.id);
onCloseSuccess();
onOpenChange(false);
} catch (err) {
const message =
err instanceof Error ? err.message : "Failed to close issue";
setError(message);
} finally {
setIsClosing(false);
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-lg">
<DialogHeader>
<DialogTitle>Close Git Project issue</DialogTitle>
<DialogDescription>
Pipeline will mark issue{" "}
<span className="font-mono font-semibold text-strong">
#{issue.forgejo_issue_number}
</span>{" "}
as closed in the connected Git provider and refresh the local issue
cache.
</DialogDescription>
</DialogHeader>
<div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-3">
<p className="break-words text-sm font-medium text-strong">
{issue.title}
</p>
{issue.body_preview ? (
<p className="mt-1 line-clamp-3 break-words text-xs text-muted">
{issue.body_preview}
</p>
) : null}
</div>
{error && (
<div className="rounded-lg border border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.08)] p-3 text-xs text-[color:var(--danger)]">
{error}
</div>
)}
<DialogFooter>
<Button
variant="outline"
onClick={() => onOpenChange(false)}
disabled={isClosing}
>
Cancel
</Button>
<Button
variant="outline"
className="border-[color:rgba(248,113,113,0.45)] text-[color:var(--danger)] hover:bg-[color:rgba(248,113,113,0.08)]"
onClick={handleClose}
disabled={isClosing}
>
{isClosing ? "Closing…" : "Close Issue"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}