// page-enroll.jsx — "Become a member": one cohesive 2-step interest form -> api/send.php const PORTAL_URL = 'https://peacefulheartsdpc.atlas.md'; const CONTACT_METHODS = ['Email', 'Phone', 'Text']; // Read ?plan= from the URL so the membership-page buttons can pre-select a tier. function getInitialPlan() { try { const p = new URLSearchParams(window.location.search).get('plan'); if (p && phPlanById(p).id === p) return p; } catch (e) { /* ignore */ } return 'founding'; } const emailOk = (v) => /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v); // US phone: must be exactly 10 digits (a leading country-code "1" is dropped). const phoneDigits = (v) => { let d = (v || '').replace(/\D/g, ''); if (d.length > 10 && d[0] === '1') d = d.slice(1); return d.slice(0, 10); }; const formatPhone = (v) => { const d = phoneDigits(v); if (d.length < 4) return d; if (d.length < 7) return `(${d.slice(0, 3)}) ${d.slice(3)}`; return `(${d.slice(0, 3)}) ${d.slice(3, 6)}-${d.slice(6)}`; }; const phoneOk = (v) => phoneDigits(v).length === 10; function EnrollFlow() { const [plan, setPlan] = useState(getInitialPlan()); const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [phone, setPhone] = useState(''); const [contactMethod, setContactMethod] = useState('Email'); const [comments, setComments] = useState(''); const [company, setCompany] = useState(''); // honeypot — real people leave this blank const [errors, setErrors] = useState({}); // { name, email, phone } const [status, setStatus] = useState('idle'); // idle | sending | sent | error const [errMsg, setErrMsg] = useState(''); const selected = phPlanById(plan); // Clear a field's error as the visitor fixes it. const setField = (setter, key) => (e) => { setter(e.target.value); if (errors[key]) setErrors((prev) => ({ ...prev, [key]: undefined })); }; const validate = () => { const errs = {}; if (!name.trim()) errs.name = 'Please enter your name.'; if (!email.trim()) errs.email = 'Please enter your email.'; else if (!emailOk(email.trim())) errs.email = 'Please enter a valid email address.'; if (!phone.trim()) errs.phone = 'Please enter a phone number.'; else if (!phoneOk(phone)) errs.phone = 'Please enter a valid 10-digit US phone number.'; return errs; }; const submit = async (e) => { e.preventDefault(); const errs = validate(); if (Object.keys(errs).length) { setErrors(errs); setStatus('error'); setErrMsg(''); return; } setStatus('sending'); setErrMsg(''); setErrors({}); try { const res = await fetch('api/send.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'enroll', plan: selected.name, planId: selected.id, planPrice: selected.price, name: name.trim(), email: email.trim(), phone: phone.trim(), contactMethod, comments: comments.trim(), company, }), }); const data = await res.json().catch(() => ({})); if (res.ok && data.ok) { setStatus('sent'); } else { setErrMsg(data.error || 'Something went wrong sending your request. Please try again.'); setStatus('error'); } } catch (err) { setErrMsg('We couldn’t reach the server. Please email info@peacefulheartsdirect.com and we’ll help.'); setStatus('error'); } }; // Confirmation — echo the details back to the visitor. if (status === 'sent') { return (

Thanks, {name.split(' ')[0]} — we’ve noted your interest.

Azra will be in touch soon (by {contactMethod.toLowerCase()}) to answer your questions and talk through membership. There’s no commitment — this just lets her know you’re interested. We’ve also emailed a copy to you.

Interested in
{selected.name} — ${selected.price}/month
Name
{name}
Email
{email}
Phone
{phone}
Preferred contact
{contactMethod}
{comments.trim() &&
Comments
{comments.trim()}
}
); } return (
{/* Step 1 — choose a plan */}
1

Choose your membership

{/* Step 2 — details */}
2

Your details

You’re interested in {selected.name} — ${selected.price}/month

Submitting this isn’t a commitment — it just lets Azra know you’re interested. She’ll reach out personally to answer questions and help you decide before anything is set up.

{errors.name && {errors.name}}
{errors.email && {errors.email}}
{ setPhone(formatPhone(e.target.value)); if (errors.phone) setErrors(p => ({ ...p, phone: undefined })); }} placeholder="(555) 123-4567" /> {errors.phone && {errors.phone}}
{/* honeypot: hidden from people, tempting to bots */} {status === 'error' && errMsg &&

{errMsg}

}

Please don’t include sensitive medical details. We’ll gather those securely later, only if you decide to join.

); } function EnrollPage() { return (

Already a member? Patient portal ↗

No surprises, ever

No copays, hidden fees, or surprise bills. Cancel with 30 days’ written notice. DPC works alongside insurance and isn’t insurance itself.

); } renderApp();