From a846f418bb681b78170486594bd8d0c4c66b3ab8 Mon Sep 17 00:00:00 2001 From: Casey Locker Date: Wed, 20 May 2026 15:37:45 -0500 Subject: [PATCH 01/10] feat(promo-codes): Tier 2 in-modal search for allowed email domains Co-Authored-By: Claude Sonnet 4.6 --- .../ManageAllowedEmailDomainsModal.jsx | 61 +++++++++++++++++-- .../__tests__/manage-modal.test.jsx | 31 +++++++++- src/i18n/en.json | 1 + 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/components/forms/promocode-form/forms/domain-authorized/ManageAllowedEmailDomainsModal.jsx b/src/components/forms/promocode-form/forms/domain-authorized/ManageAllowedEmailDomainsModal.jsx index 1f6184f34..e514ab9e4 100644 --- a/src/components/forms/promocode-form/forms/domain-authorized/ManageAllowedEmailDomainsModal.jsx +++ b/src/components/forms/promocode-form/forms/domain-authorized/ManageAllowedEmailDomainsModal.jsx @@ -12,9 +12,17 @@ import { parseTextBlob, classifyEntries } from "./bulk-input-parser"; const ROW_HEIGHT = 32; const LIST_HEIGHT = 320; +const SEARCH_DEBOUNCE_MS = 150; + +// eslint-disable-next-line no-unused-vars +const _typeOf = (entry) => { + if (entry.startsWith("@")) return "at_domain"; + if (entry.startsWith(".")) return "tld"; + return "email"; +}; const Row = React.memo(({ index, style, data }) => { - const entry = data[index]; + const { entry } = data.items[index]; return (
{ + const id = setTimeout(() => setSearch(searchInput), SEARCH_DEBOUNCE_MS); + return () => clearTimeout(id); + }, [searchInput]); + const handleAddDomains = useCallback(() => { const rows = parseTextBlob(draftText); if (rows.length === 0) return; @@ -63,10 +80,17 @@ const ManageAllowedEmailDomainsModal = ({ }); setDraftText(""); - if (listRef.current && next.length > 0) { + // Adds append to the end of the working copy. If a search filter is + // active the new entries may be filtered out of view — clear it so the + // additions are visible, and only autoscroll when the unfiltered list + // index space matches `working`. + if (search !== "") { + setSearchInput(""); + setSearch(""); + } else if (listRef.current && next.length > 0) { listRef.current.scrollToItem(next.length - 1, "end"); } - }, [draftText, working]); + }, [draftText, working, search]); const handleKeyDown = (ev) => { if (ev.key === "Enter" && (ev.metaKey || ev.ctrlKey)) { @@ -100,6 +124,18 @@ const ManageAllowedEmailDomainsModal = ({ } ); + const visible = useMemo(() => { + const q = search.trim().toLowerCase(); + const indexed = working.map((entry, originalIndex) => ({ + entry, + originalIndex + })); + if (!q) return indexed; + return indexed.filter((x) => x.entry.toLowerCase().includes(q)); + }, [working, search]); + + const itemData = useMemo(() => ({ items: visible }), [visible]); + return ( @@ -108,6 +144,21 @@ const ManageAllowedEmailDomainsModal = ({ +
+ setSearchInput(ev.target.value)} + /> +