Homeowners picker filtered by case

X-Lovable-Edit-ID: edt-7ee11b00-4054-4eb9-8653-a9f021b62853
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-19 23:49:36 +00:00
co-authored by renee-png
+20 -25
View File
@@ -171,12 +171,13 @@ export function CaseCollectionsTab({
const list = cols ?? [];
setCollections(list);
setHomeowners(hos ?? []);
// Filter: case_contacts.role = 'homeowner' OR contact.contact_type = 'homeowner'
// Only case-linked contacts whose role OR contact_type is 'homeowner' or 'tenant'
const ALLOWED = new Set(["homeowner", "tenant"]);
const hoContacts = (ccs ?? [])
.filter((cc: any) => {
const roleMatch = (cc.role || "").toLowerCase() === "homeowner";
const typeMatch = (cc.contact?.contact_type || "").toLowerCase() === "homeowner";
return cc.contact && (roleMatch || typeMatch);
const role = (cc.role || "").toLowerCase();
const type = (cc.contact?.contact_type || "").toLowerCase();
return cc.contact && (ALLOWED.has(role) || ALLOWED.has(type));
})
.map((cc: any) => ({ ...cc.contact, _link_role: cc.role }));
setContactHomeowners(hoContacts);
@@ -1145,8 +1146,7 @@ function AddCollectionDialog({
useEffect(() => {
if (open) {
const match = findUniqueHomeownerByTitle(caseTitle, available);
setPickerValue(match ? `ho:${match.id}` : "");
setPickerValue("");
setStatus("none");
setNotes("");
}
@@ -1221,19 +1221,16 @@ function AddCollectionDialog({
onCreated();
};
const hoOptions = available.map((h) => ({
value: `ho:${h.id}`,
label: `${h.last_name}, ${h.first_name}${h.unit_number ? ` — Unit ${h.unit_number}` : ""}`,
keywords: `${h.first_name} ${h.last_name} ${h.unit_number ?? ""}`,
group: "HOA homeowners",
}));
const ctOptions = contactOptions.map(({ contact, first, last }) => ({
value: `ct:${contact.id}`,
label: `${last || contact.name}${first ? `, ${first}` : ""} — Case contact`,
keywords: `${first} ${last} ${contact.name} ${contact.email ?? ""}`,
group: "Case contacts (homeowner)",
}));
const allOptions = [...hoOptions, ...ctOptions];
const ctOptions = contactOptions.map(({ contact, first, last }) => {
const roleLabel = (contact._link_role || contact.contact_type || "homeowner").toLowerCase();
const niceRole = roleLabel.charAt(0).toUpperCase() + roleLabel.slice(1);
return {
value: `ct:${contact.id}`,
label: `${last || contact.name}${first ? `, ${first}` : ""} — ${niceRole}`,
keywords: `${first} ${last} ${contact.name} ${contact.email ?? ""}`,
};
});
const allOptions = ctOptions;
return (
<Dialog open={open} onOpenChange={onOpenChange}>
@@ -1241,9 +1238,8 @@ function AddCollectionDialog({
<DialogHeader>
<DialogTitle className="font-serif">Add homeowner collection</DialogTitle>
<DialogDescription>
Attach a homeowner to this matter. You can pick from this HOA's
homeowners or any case contact tagged as a homeowner. Each
homeowner can only have one collection per case.
Pick a case contact tagged as a homeowner or tenant. Link contacts
on the Contacts tab of this case to make them available here.
</DialogDescription>
</DialogHeader>
<div className="space-y-3">
@@ -1251,9 +1247,8 @@ function AddCollectionDialog({
<Label>Homeowner</Label>
{allOptions.length === 0 ? (
<p className="text-sm text-muted-foreground italic mt-1">
{homeowners.length === 0 && contactHomeowners.length === 0
? "No homeowners yet. Use 'New homeowner' or link a homeowner contact to this case."
: "All available homeowners already have a collection on this matter."}
No case contacts tagged as homeowner or tenant. Add one on the
Contacts tab of this case.
</p>
) : (
<SearchableSelect