simplify second modal

This commit is contained in:
Khalim Conn-Kowlessar 2026-05-06 18:27:28 +00:00
parent e6e94176cd
commit ffb2f8c7c3

View file

@ -2,7 +2,7 @@
import { useEffect, useMemo, useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { X, CheckCircle2, Circle, AlertTriangle, ChevronRight, ChevronDown, Trash2, RotateCcw } from "lucide-react";
import { X, CheckCircle2, Circle, AlertTriangle, ChevronRight, ChevronDown, Trash2, RotateCcw, Loader2 } from "lucide-react";
import {
Drawer,
DrawerClose,
@ -1562,12 +1562,13 @@ export function InstructMeasureEditor({
);
const [checked, setChecked] = useState<Set<string>>(new Set());
const [confirmOpen, setConfirmOpen] = useState(false);
const [confirmText, setConfirmText] = useState("");
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
setChecked(new Set());
setConfirmText("");
setError(null);
}, [dealId]);
@ -1582,10 +1583,9 @@ export function InstructMeasureEditor({
});
}
async function handleConfirm() {
async function handleSubmit() {
const measureNames = Array.from(checked);
if (measureNames.length === 0) return;
setConfirmOpen(false);
if (measureNames.length === 0 || confirmText !== "confirm") return;
setSubmitting(true);
setError(null);
try {
@ -1612,6 +1612,7 @@ export function InstructMeasureEditor({
hubspotError?: string;
};
setChecked(new Set());
setConfirmText("");
void queryClient.invalidateQueries({ queryKey: ["pibiMeasures", portfolioId, dealId] });
onSuccess?.();
if (json.hubspotSync === "failed") {
@ -1637,6 +1638,9 @@ export function InstructMeasureEditor({
}
}
const hasSelection = checked.size > 0;
const canSubmit = hasSelection && confirmText === "confirm" && !submitting;
return (
<div className="space-y-3">
{outOfOrderWarning && (
@ -1675,17 +1679,46 @@ export function InstructMeasureEditor({
</div>
)}
</div>
{eligible.length > 0 && (
<button
type="button"
data-testid="instruct-measure-submit"
onClick={() => setConfirmOpen(true)}
disabled={checked.size === 0 || submitting}
className="text-xs font-medium px-3 py-1.5 rounded-lg bg-brandblue text-white hover:bg-brandmidblue disabled:opacity-50 transition-colors"
>
Instruct selected ({checked.size})
</button>
{hasSelection && (
<div className="space-y-2 border-t border-gray-100 pt-3">
<div className="flex flex-wrap gap-1">
{Array.from(checked).map((m) => (
<span
key={m}
className="px-2 py-0.5 rounded-full text-[11px] bg-blue-50 border border-blue-200 text-blue-700"
>
{m}
</span>
))}
</div>
<label className="flex flex-col gap-1">
<span className="text-xs text-gray-500">
Type <span className="font-mono font-semibold">confirm</span> to instruct
</span>
<input
data-testid="instruct-measure-confirm-input"
type="text"
value={confirmText}
onChange={(e) => setConfirmText(e.target.value)}
disabled={submitting}
placeholder="confirm"
className="rounded-lg border border-gray-200 px-3 py-1.5 text-xs text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-300 w-full"
/>
</label>
<button
type="button"
data-testid="instruct-measure-submit"
onClick={handleSubmit}
disabled={!canSubmit}
className="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg bg-brandblue text-white hover:bg-brandmidblue disabled:opacity-50 transition-colors"
>
{submitting && <Loader2 className="h-3.5 w-3.5 animate-spin" />}
{submitting ? "Instructing…" : `Instruct ${checked.size} measure${checked.size === 1 ? "" : "s"}`}
</button>
</div>
)}
{error && (
<p
data-testid="instruct-measure-error"
@ -1694,44 +1727,6 @@ export function InstructMeasureEditor({
{error}
</p>
)}
<Dialog open={confirmOpen} onOpenChange={setConfirmOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Instruct measures</DialogTitle>
</DialogHeader>
<p className="text-sm text-gray-600">
The following measures will be instructed and approved:
</p>
<ul className="mt-2 space-y-1">
{Array.from(checked).map((m) => (
<li key={m} className="flex items-center gap-2 text-sm text-gray-800">
<CheckCircle2 className="h-4 w-4 text-brandblue shrink-0" />
{m}
</li>
))}
</ul>
<DialogFooter className="mt-4">
<button
type="button"
onClick={() => setConfirmOpen(false)}
disabled={submitting}
className="text-xs font-medium px-3 py-1.5 rounded-lg border border-gray-200 text-gray-600 hover:bg-gray-50 disabled:opacity-50 transition-colors"
>
Cancel
</button>
<button
type="button"
data-testid="instruct-measure-confirm"
onClick={handleConfirm}
disabled={submitting}
className="text-xs font-medium px-3 py-1.5 rounded-lg bg-brandblue text-white hover:bg-brandmidblue disabled:opacity-50 transition-colors"
>
{submitting ? "Instructing…" : "Confirm"}
</button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}