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:
@@ -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)} />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user