Deploy
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
'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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user