63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { FormEvent, useState } from "react";
|
|
import Modal from "../ui/Modal";
|
|
|
|
type ApprovalActionModalProps = {
|
|
isOpen: boolean;
|
|
mode: "approve" | "reject";
|
|
title: string;
|
|
onSubmit: (notes?: string, checkerRole?: string) => Promise<void>;
|
|
onClose: () => void;
|
|
};
|
|
|
|
export default function ApprovalActionModal({
|
|
isOpen,
|
|
mode,
|
|
title,
|
|
onSubmit,
|
|
onClose
|
|
}: ApprovalActionModalProps) {
|
|
const [notes, setNotes] = useState("");
|
|
const [checkerRole, setCheckerRole] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleSubmit = async (e: FormEvent) => {
|
|
e.preventDefault();
|
|
setLoading(true);
|
|
try {
|
|
await onSubmit(notes, checkerRole || undefined);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal isOpen={isOpen} title={title} onClose={onClose}>
|
|
<form className="vstack gap-3" onSubmit={handleSubmit}>
|
|
<textarea
|
|
className="form-control"
|
|
rows={4}
|
|
value={notes}
|
|
onChange={(e) => setNotes(e.target.value)}
|
|
placeholder="Notes"
|
|
/>
|
|
<input
|
|
className="form-control"
|
|
value={checkerRole}
|
|
onChange={(e) => setCheckerRole(e.target.value)}
|
|
placeholder="Optional checker role (defaults to CHECKER)"
|
|
/>
|
|
<div className="d-flex justify-content-end gap-2">
|
|
<button type="button" className="btn btn-outline-secondary" onClick={onClose}>
|
|
Cancel
|
|
</button>
|
|
<button className="btn btn-primary" disabled={loading} type="submit">
|
|
{loading ? "Saving..." : mode === "approve" ? "Approve" : "Reject"}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</Modal>
|
|
);
|
|
}
|