diff --git a/src/app/portfolio/[slug]/properties/add/AddPropertiesClient.tsx b/src/app/portfolio/[slug]/properties/add/AddPropertiesClient.tsx index 81707862..4276e4a0 100644 --- a/src/app/portfolio/[slug]/properties/add/AddPropertiesClient.tsx +++ b/src/app/portfolio/[slug]/properties/add/AddPropertiesClient.tsx @@ -44,6 +44,7 @@ export default function AddPropertiesClient({ const [input, setInput] = useState(""); const [inputError, setInputError] = useState(null); const [search, setSearch] = useState<{ pc: string; refresh: number } | null>(null); + const [filter, setFilter] = useState(""); const [basket, setBasket] = useState({}); const [done, setDone] = useState<{ added: number; skipped: number } | null>(null); @@ -110,6 +111,7 @@ export default function AddPropertiesClient({ } setInputError(null); setDone(null); + setFilter(""); setSearch({ pc, refresh: 0 }); }; @@ -130,6 +132,12 @@ export default function AddPropertiesClient({ const addable = data ? data.candidates.filter((c) => c.selectable && !c.alreadyInPortfolio) : []; + const needle = filter.trim().toLowerCase(); + const visible = data + ? needle + ? data.candidates.filter((c) => c.address.toLowerCase().includes(needle)) + : data.candidates + : []; const totalSelected = countSelected(basket); const postcodes = Object.keys(basket); @@ -267,7 +275,9 @@ export default function AddPropertiesClient({

{data.postcode}

- {data.candidates.length}{" "} + {needle + ? `${visible.length} of ${data.candidates.length}` + : data.candidates.length}{" "} {data.candidates.length === 1 ? "address" : "addresses"} {addable.length > 0 && ( @@ -307,10 +317,40 @@ export default function AddPropertiesClient({
+ {/* Long postcodes can return ~100 addresses — a filter lets the user + jump to a house number or street name without scrolling. */} + {data.candidates.length > 8 && ( +
+ + setFilter(e.target.value)} + placeholder="Filter these addresses…" + spellCheck={false} + autoComplete="off" + className="w-full border border-slate-200 rounded-xl pl-9 pr-9 py-2 text-sm focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/10" + /> + {filter && ( + + )} +
+ )} + {/* Long postcodes can return ~100 addresses — scroll inside the card rather than growing the page. */}
- {data.candidates.map((c) => { + {visible.length === 0 ? ( +

+ No addresses match “{filter.trim()}”. +

+ ) : ( + visible.map((c) => { const { label, note } = describeCandidate(c); const disabled = !c.selectable || c.alreadyInPortfolio; const isSelected = !!selected[c.uprn]; @@ -361,7 +401,8 @@ export default function AddPropertiesClient({ ); - })} + }) + )}
)}