Added Property Address field

X-Lovable-Edit-ID: edt-2e4bc3ac-3416-4bee-a356-94cf7d03a881
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-26 09:01:15 +00:00
co-authored by renee-png
5 changed files with 60 additions and 2 deletions
+37 -2
View File
@@ -645,6 +645,33 @@ export function CollectionDetail({
.maybeSingle();
const firmName = (firm as any)?.company_name || "";
// Look up a linked Homeowner-type contact on this case to pull its
// property_address (preferred over the homeowner record's address).
let contactPropertyAddress: string | null = null;
try {
const { data: linkedContacts } = await supabase
.from("case_contacts")
.select("contact:contacts(name, email, contact_type, property_address)")
.eq("case_id", collection.case_id);
const homeownerContacts = (linkedContacts || [])
.map((r: any) => r.contact)
.filter((c: any) => c && c.contact_type === "homeowner");
// Prefer match by email or name to the collection's homeowner
const hoFullName = `${ho?.first_name ?? ""} ${ho?.last_name ?? ""}`.trim().toLowerCase();
const hoEmail = (ho?.email || "").toLowerCase();
const matched =
homeownerContacts.find(
(c: any) =>
(hoEmail && (c.email || "").toLowerCase() === hoEmail) ||
(hoFullName && (c.name || "").toLowerCase() === hoFullName),
) || homeownerContacts[0];
if (matched?.property_address) {
contactPropertyAddress = matched.property_address;
}
} catch {
// ignore — fall back to homeowner record address
}
const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "letter" });
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
@@ -673,8 +700,16 @@ export function CollectionDetail({
doc.text("PROPERTY ADDRESS:", margin, 88);
doc.setFont("helvetica", "normal");
const addrLines: string[] = [];
if (ho?.address) addrLines.push(ho.address);
if (ho?.unit_number) addrLines.push(`Unit ${ho.unit_number}`);
if (contactPropertyAddress) {
// Split multi-line property address into lines
contactPropertyAddress.split(/\r?\n/).forEach((l) => {
const t = l.trim();
if (t) addrLines.push(t);
});
} else {
if (ho?.address) addrLines.push(ho.address);
if (ho?.unit_number) addrLines.push(`Unit ${ho.unit_number}`);
}
if (addrLines.length === 0) addrLines.push("N/A");
addrLines.forEach((line, i) => doc.text(line, margin, 102 + i * 12));
@@ -40,6 +40,7 @@ export interface ContactRecord {
postal_code?: string | null;
notes?: string | null;
contact_type?: string | null;
property_address?: string | null;
}
export function ContactFormDialog({
@@ -92,6 +93,7 @@ export function ContactFormDialog({
postal_code: form.postal_code || null,
notes: form.notes || null,
contact_type: form.contact_type || "other",
property_address: form.property_address || null,
};
let saved: { id: string; name: string } | null = null;
if (contact?.id) {
@@ -185,6 +187,19 @@ export function ContactFormDialog({
<Label>Postal code</Label>
<Input value={form.postal_code ?? ""} onChange={(e) => set("postal_code", e.target.value)} />
</div>
{form.contact_type === "homeowner" && (
<div className="space-y-1.5 sm:col-span-2">
<Label>Property address</Label>
<Input
placeholder="Street, unit, city, state ZIP"
value={form.property_address ?? ""}
onChange={(e) => set("property_address", e.target.value)}
/>
<p className="text-xs text-muted-foreground">
Used as the property address on collection ledger statements.
</p>
</div>
)}
<div className="space-y-1.5 sm:col-span-2">
<Label>Notes</Label>
<Textarea rows={3} value={form.notes ?? ""} onChange={(e) => set("notes", e.target.value)} />
+3
View File
@@ -1059,6 +1059,7 @@ export type Database = {
notes: string | null
phone: string | null
postal_code: string | null
property_address: string | null
state: string | null
title: string | null
updated_at: string
@@ -1079,6 +1080,7 @@ export type Database = {
notes?: string | null
phone?: string | null
postal_code?: string | null
property_address?: string | null
state?: string | null
title?: string | null
updated_at?: string
@@ -1099,6 +1101,7 @@ export type Database = {
notes?: string | null
phone?: string | null
postal_code?: string | null
property_address?: string | null
state?: string | null
title?: string | null
updated_at?: string
+3
View File
@@ -128,6 +128,9 @@ function ContactDetail() {
<DetailRow label="Company" value={contact.company} icon={Building2} />
<DetailRow label="Title" value={contact.title} />
<DetailRow label="Address" value={addr || null} icon={MapPin} />
{contact.contact_type === "homeowner" && (
<DetailRow label="Property address" value={contact.property_address || null} icon={MapPin} />
)}
</dl>
{contact.notes && (
<div className="mt-4 pt-4 border-t">
@@ -0,0 +1,2 @@
ALTER TABLE public.contacts
ADD COLUMN IF NOT EXISTS property_address text;