Deploy
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, type ChangeEvent } from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { ArrowRight } from 'lucide-react'
|
||||||
|
import Button from '@/components/ui/Button'
|
||||||
|
import Input from '@/components/ui/Input'
|
||||||
|
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'
|
||||||
|
import BusinessContact from '@/components/BusinessContact'
|
||||||
|
import BusinessHours from '@/components/BusinessHours'
|
||||||
|
import BusinessMap from '@/components/BusinessMap'
|
||||||
|
import { useEnquiry } from '@/hooks/useEnquiry'
|
||||||
|
|
||||||
|
type Form = { name: string; phone: string; email: string; message: string }
|
||||||
|
|
||||||
|
export default function VisitTheClinicSection() {
|
||||||
|
const enquiry = useEnquiry()
|
||||||
|
const [form, setForm] = useState<Form>({ name: '', phone: '', email: '', message: '' })
|
||||||
|
const [result, setResult] = useState<{ ok: boolean; message: string } | null>(null)
|
||||||
|
const [sending, setSending] = useState(false)
|
||||||
|
|
||||||
|
const set =
|
||||||
|
(key: keyof Form) =>
|
||||||
|
(e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>
|
||||||
|
setForm((f) => ({ ...f, [key]: e.target.value }))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section data-vula-section="visittheclinic" id="visit-the-clinic" className="bg-muted text-foreground py-20 sm:py-24">
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="grid gap-12 lg:grid-cols-12">
|
||||||
|
<div className="lg:col-span-7">
|
||||||
|
<span className="text-xs font-semibold uppercase tracking-[0.18em] text-primary">Visit the clinic</span>
|
||||||
|
<h2 className="mt-3 text-3xl font-bold leading-tight sm:text-4xl">
|
||||||
|
Come in for an adjustment, or send us a message first.
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 max-w-[44ch] text-base text-muted-foreground">
|
||||||
|
The practice is set up for families: a pram fits through the door, there is room for kids in the waiting area, and a newborn check does not need a full adult appointment slot.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-8 space-y-6">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">Where to find us</h3>
|
||||||
|
<BusinessContact className="mt-2 text-sm text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
<BusinessHours title="Clinic hours" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<BusinessMap />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="lg:col-span-5">
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Send a message</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{result?.ok ? (
|
||||||
|
<p className="text-sm leading-relaxed text-foreground">{result.message}</p>
|
||||||
|
) : enquiry.available ? (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<Input label="Your name" value={form.name} onChange={set('name')} />
|
||||||
|
<Input label="Phone or WhatsApp number" value={form.phone} onChange={set('phone')} />
|
||||||
|
<Input label="Email (optional)" type="email" value={form.email} onChange={set('email')} />
|
||||||
|
<div>
|
||||||
|
<label htmlFor="visit-message" className="mb-1 block text-sm font-medium text-foreground">
|
||||||
|
What would you like help with?
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="visit-message"
|
||||||
|
rows={4}
|
||||||
|
value={form.message}
|
||||||
|
onChange={set('message')}
|
||||||
|
className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none transition-all duration-200 ease-out focus:border-primary focus:ring-2 focus:ring-primary/30"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{result && !result.ok ? (
|
||||||
|
<p className="text-sm font-medium text-foreground">{result.message}</p>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-3 pt-2">
|
||||||
|
{enquiry.channels.map((channel) => (
|
||||||
|
<Button
|
||||||
|
key={channel}
|
||||||
|
type="button"
|
||||||
|
fullWidth
|
||||||
|
disabled={sending}
|
||||||
|
variant={channel === 'whatsapp' ? 'default' : 'outline'}
|
||||||
|
onClick={async () => {
|
||||||
|
if (!form.name.trim() || !form.phone.trim()) {
|
||||||
|
setResult({ ok: false, message: 'Please add your name and a contact number so the practice can reach you.' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setSending(true)
|
||||||
|
const res = await enquiry.send(form, channel)
|
||||||
|
setResult(res)
|
||||||
|
setSending(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{channel === 'whatsapp' ? 'Send on WhatsApp' : 'Send by email'}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Online messaging is not switched on yet. Book a time from the services page and the practice will confirm it with you directly.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<div className="mt-6 rounded-lg bg-card p-6 shadow-md transition-all duration-200 ease-out hover:-translate-y-1 hover:shadow-xl">
|
||||||
|
<p className="text-base font-semibold text-foreground">Prefer to pick a time yourself?</p>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">Choose a slot online and the practice confirms it with you.</p>
|
||||||
|
<Button asChild fullWidth className="mt-4">
|
||||||
|
<Link href="/services">
|
||||||
|
Book an appointment
|
||||||
|
<ArrowRight className="ml-2 h-4 w-4" />
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user