shoc-frontend-new/src/app/(protected)/locations/_components/site-map-preview.tsx
Alexandre Brandizzi f0b4ced660 feat(sites): show the site address map preview through one shared Maps helper
Vendors and Sites now build the keyless embed URL and the Open in Google
Maps link through one helper. The Site map shows the placeholder only in
the Add/Edit forms; view mode and the Work Order Site dialog always render
it for the saved address, the dialog in its compact form.
2026-09-25 13:39:29 -03:00

69 lines
2.3 KiB
TypeScript

import { Box, Typography } from "@mui/material";
import { MapPin } from "lucide-react";
import type { Location } from "@/domain/locations/types/location";
import { buildSiteMapEmbedUrl, hasCompleteSiteAddress } from "@/domain/locations/utils/site-maps";
type SiteMapPreviewProps = Pick<Location, "address" | "city" | "state" | "zipCode"> & {
/**
* Add/Edit forms: hold the map back behind a placeholder until Street, City
* and State are all filled, so a half-typed address never points somewhere
* misleading. Saved sites (view mode, Work Order Site dialog) leave this off
* and always render the map for whatever address they have.
*/
placeholderUntilComplete?: boolean;
/** Hide the "Location preview" caption where the map sits inside an info box. */
hideLabel?: boolean;
height?: number;
};
function MapPlaceholder({ height }: { height: number }) {
return (
<Box
role="status"
className="mt-1 flex flex-col items-center justify-center gap-1 rounded-lg"
sx={{ height, bgcolor: "var(--color-bg-muted)", border: 1, borderColor: "divider" }}
>
<MapPin size={18} aria-hidden style={{ color: "var(--color-text-muted)" }} />
<Typography variant="body2" sx={{ color: "text.secondary" }}>
Enter an address to preview the location
</Typography>
</Box>
);
}
/** Read-only key-less Google Maps embed of a site's address. */
export function SiteMapPreview({
placeholderUntilComplete = false,
hideLabel = false,
height = 140,
...address
}: SiteMapPreviewProps) {
const src = buildSiteMapEmbedUrl(address);
const showMap = placeholderUntilComplete ? hasCompleteSiteAddress(address) : Boolean(src);
if (!showMap && !placeholderUntilComplete) {
return null;
}
return (
<Box>
{!hideLabel && (
<Typography variant="caption" sx={{ color: "text.secondary" }}>
Location preview
</Typography>
)}
{showMap && (
<Box
component="iframe"
title="Site location map"
src={src}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
className="mt-1 block w-full rounded-lg border-0"
sx={{ height }}
/>
)}
{!showMap && <MapPlaceholder height={height} />}
</Box>
);
}