diff --git a/nt-fe/app/(treasury)/[treasuryId]/dashboard/components/select-modal.tsx b/nt-fe/app/(treasury)/[treasuryId]/dashboard/components/select-modal.tsx index a1bc05aed..3fa99c6b6 100644 --- a/nt-fe/app/(treasury)/[treasuryId]/dashboard/components/select-modal.tsx +++ b/nt-fe/app/(treasury)/[treasuryId]/dashboard/components/select-modal.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useMemo, useCallback, ReactNode } from "react"; +import { useState, useMemo, useCallback, useEffect, useRef, ReactNode } from "react"; import { Check } from "lucide-react"; import { useTranslations } from "next-intl"; import { Input } from "@/components/input"; @@ -72,6 +72,17 @@ export function SelectModal({ }: SelectModalProps) { const t = useTranslations("selectModal"); const [searchQuery, setSearchQuery] = useState(""); + // Guard against rapid double-clicks: once a selection fires, ignore any + // subsequent clicks until the dialog has closed and re-opened. + const isSelectingRef = useRef(false); + + // Reset the guard whenever the modal opens so it's ready for the next session. + useEffect(() => { + if (isOpen) { + isSelectingRef.current = false; + } + }, [isOpen]); + const effectiveSearchPlaceholder = searchPlaceholder ?? t("searchByName"); const filteredOptions = useMemo(() => { @@ -109,6 +120,12 @@ export function SelectModal({ const handleSelect = useCallback( (option: SelectOption) => { + // Prevent a rapid double-click from triggering the handler twice (single-select only). + // For multi-select we must allow multiple item clicks while the modal remains open. + if (!multiSelect) { + if (isSelectingRef.current) return; + isSelectingRef.current = true; + } onSelect(option); if (!multiSelect) { setSearchQuery("");