diff --git a/src/components/BusinessMap.tsx b/src/components/BusinessMap.tsx new file mode 100644 index 0000000..06ee435 --- /dev/null +++ b/src/components/BusinessMap.tsx @@ -0,0 +1,88 @@ +'use client' +import { useEffect, useState } from 'react' + +interface Address { + street: string | null + locality: string | null + region: string | null + postalCode: string | null + country: string | null +} +interface Profile { + businessName: string | null + address: Address | null +} + +/** One line a map search understands, in South African order. */ +export function placeFor(a: Address): string { + const country = !a.country || a.country === 'ZA' ? 'South Africa' : a.country + return [a.street, a.locality, [a.region, a.postalCode].filter(Boolean).join(' '), country] + .filter(Boolean) + .join(', ') +} + +/** + * The business's own address on a map, with directions. + * + * Nothing at all until the owner has entered a full address. The map is + * loaded when a visitor asks for it, not before. + */ +export default function BusinessMap({ className = '' }: { className?: string }) { + const [p, setP] = useState(null) + const [show, setShow] = useState(false) + + useEffect(() => { + const base = process.env.NEXT_PUBLIC_VULA_COMMERCE_URL + const id = process.env.NEXT_PUBLIC_VULA_PROJECT_ID + if (!base || !id) return + let live = true + fetch(base + '/api/public/profile/' + id) + .then((r) => (r.ok ? r.json() : null)) + .then((d) => { if (live && d?.profile) setP(d.profile) }) + .catch(() => { /* no map is where we already were */ }) + return () => { live = false } + }, []) + + const a = p?.address + if (!a) return null + const q = encodeURIComponent(placeFor(a)) + const name = p?.businessName || 'our location' + + return ( +
+ {show ? ( +