Files
vula-f7951bab/src/components/BusinessContact.tsx
T
Vula Builder e5e4e80cfd Deploy
2026-10-11 14:20:22 +00:00

74 lines
2.5 KiB
TypeScript

'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
phone: string | null
email: string | null
whatsapp: string | null
/** null unless BOTH a street and a town are set — half an address sends
* people to the wrong place, so the server withholds it rather than
* leaving each caller to decide. */
address: Address | null
}
/**
* The business's own contact details, as the owner entered them.
*
* Shows nothing at all until she has entered something. That is deliberate:
* blank is honest, and a plausible-looking address nobody typed is not.
*/
export default function BusinessContact({ className = '' }: { className?: string }) {
const [p, setP] = useState<Profile | null>(null)
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(() => { /* a footer without an address is where we already were */ })
return () => { live = false }
}, [])
if (!p) return null
const a = p.address
// South African postal order: street, then town, then province and code.
// Joining the code to the TOWN and leaving the province after it reads as a
// foreign format badly translated — "Johannesburg 3900 / KwaZulu-Natal" is
// not how anyone here writes an address, or how a courier reads one.
// Province and code share the last line so a short address stays three lines
// rather than four, and either alone still renders sensibly.
const lines = a
? [a.street, a.locality, [a.region, a.postalCode].filter(Boolean).join(', ')].filter(Boolean)
: []
if (!lines.length && !p.phone && !p.email) return null
return (
<address className={'not-italic space-y-1 ' + className}>
{lines.map((line) => (
<div key={line}>{line}</div>
))}
{p.phone && (
<div>
<a href={'tel:' + p.phone.replace(/[^0-9+]/g, '')} className="hover:underline">{p.phone}</a>
</div>
)}
{p.email && (
<div>
<a href={'mailto:' + p.email} className="hover:underline">{p.email}</a>
</div>
)}
</address>
)
}