diff --git a/src/app/(protected)/workorders/_components/list/table/cells/vendor-dialog-company-card.tsx b/src/app/(protected)/workorders/_components/list/table/cells/vendor-dialog-company-card.tsx index b14f8a4a..e7bea00d 100644 --- a/src/app/(protected)/workorders/_components/list/table/cells/vendor-dialog-company-card.tsx +++ b/src/app/(protected)/workorders/_components/list/table/cells/vendor-dialog-company-card.tsx @@ -1,4 +1,6 @@ import { ExternalLink, Mail, MapPin } from "lucide-react"; +import { AddressMapPreview } from "@/components/common/address-map-preview"; +import { mapsSearchUrl } from "@/lib/address/vendor-address"; import { Detail } from "@/app/(protected)/workorders/_components/wizard/wizard-labels"; import type { VendorDropdownItem } from "@/domain/work-orders/types/work-order"; import { formatVendorDistance } from "@/domain/work-orders/utils/vendor-dropdown-label"; @@ -33,15 +35,23 @@ export function VendorDialogCompanyCard({ company, vendor }: VendorDialogCompany {Boolean(vendor?.address) && } {Boolean(email) && } {vendor != null && Boolean(vendor.address) && ( - - Open in Google Maps - + <> + + Open in Google Maps + + {/* + SH-271: the vendor dropdown payload carries one composed address + line, not the structured parts the form and detail drawer hold, so + the preview is given the line directly. It is saved data either way. + */} + + )} ); diff --git a/src/components/common/address-map-preview.tsx b/src/components/common/address-map-preview.tsx index a9b14ad9..91eee654 100644 --- a/src/components/common/address-map-preview.tsx +++ b/src/components/common/address-map-preview.tsx @@ -7,7 +7,14 @@ import { } from "@/lib/address/vendor-address"; type AddressMapPreviewProps = { - address: Partial; + /** Structured parts, as held by a form or a detail view. */ + address?: Partial; + /** + * An already-composed address line, for callers that hold saved data rather + * than live input — the Work Order vendor dialog gets one string from the + * vendor dropdown payload. Ignored when `address` is given. + */ + query?: string; height?: number; }; @@ -21,10 +28,16 @@ type AddressMapPreviewProps = { * Renders nothing until Street, City and State are all present — a preview of a * half-typed address points somewhere misleading, which is worse than no map. */ -export function AddressMapPreview({ address, height = 160 }: AddressMapPreviewProps) { - if (!hasCompleteAddress(address)) return null; - - const query = buildAddressQuery(address); +export function AddressMapPreview({ + address, + query: rawQuery, + height = 160, +}: AddressMapPreviewProps) { + // Structured input is held to the completeness rule; a pre-composed line is + // saved data and only has to be non-empty. + const query = address ? buildAddressQuery(address) : (rawQuery ?? "").trim(); + const renderable = address ? hasCompleteAddress(address) : Boolean(query); + if (!renderable) return null; return (