233 lines
7.6 KiB
TypeScript
233 lines
7.6 KiB
TypeScript
import axios from 'axios';
|
|
import Head from 'next/head';
|
|
import Link from 'next/link';
|
|
import React from 'react';
|
|
import LayoutGuest from '../layouts/Guest';
|
|
import { getPageTitle } from '../config';
|
|
|
|
const fieldClass =
|
|
'mt-2 w-full rounded-none border border-[#19192d]/10 bg-white px-4 py-3 text-[#19192d] outline-none focus:border-[#35b7a5] focus:ring-2 focus:ring-[#35b7a5]/15';
|
|
|
|
type IntakeValues = {
|
|
name: string;
|
|
email: string;
|
|
company: string;
|
|
role_title: string;
|
|
goal: string;
|
|
challenge: string;
|
|
desired_outcome: string;
|
|
consent_ai_notes: boolean;
|
|
};
|
|
|
|
const emptyValues: IntakeValues = {
|
|
name: '',
|
|
email: '',
|
|
company: '',
|
|
role_title: '',
|
|
goal: '',
|
|
challenge: '',
|
|
desired_outcome: '',
|
|
consent_ai_notes: false,
|
|
};
|
|
|
|
function FieldLabel({
|
|
label,
|
|
children,
|
|
}: {
|
|
label: string;
|
|
children: React.ReactNode;
|
|
}) {
|
|
return (
|
|
<label className='block'>
|
|
<span className='text-sm font-semibold text-[#72798a]'>{label}</span>
|
|
{children}
|
|
</label>
|
|
);
|
|
}
|
|
|
|
export default function Intake() {
|
|
const [values, setValues] = React.useState<IntakeValues>(emptyValues);
|
|
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
const [isSubmitted, setIsSubmitted] = React.useState(false);
|
|
|
|
function updateValue(field: keyof IntakeValues, value: string | boolean) {
|
|
setValues((current) => {
|
|
return {
|
|
...current,
|
|
[field]: value,
|
|
};
|
|
});
|
|
}
|
|
|
|
async function submitIntake(event: React.FormEvent) {
|
|
event.preventDefault();
|
|
setIsSubmitting(true);
|
|
await axios.post('/coaching-public/intake', {
|
|
...values,
|
|
source: 'website',
|
|
});
|
|
setIsSubmitted(true);
|
|
setIsSubmitting(false);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{getPageTitle('Start coaching')}</title>
|
|
</Head>
|
|
<main className='min-h-screen bg-[#fffdf9] text-[#19192d]'>
|
|
<header className='px-5 py-5'>
|
|
<div className='mx-auto flex max-w-6xl items-center justify-between'>
|
|
<Link href='/' className='font-semibold'>
|
|
Coaching SaaS Workspace
|
|
</Link>
|
|
<Link
|
|
href='/login/'
|
|
className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold'
|
|
>
|
|
Login
|
|
</Link>
|
|
</div>
|
|
</header>
|
|
|
|
<section className='mx-auto grid max-w-6xl gap-8 px-5 py-10 lg:grid-cols-[0.85fr_1.15fr]'>
|
|
<div>
|
|
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
|
|
Coaching intake
|
|
</p>
|
|
<h1 className='mt-4 font-serif text-5xl font-semibold leading-tight md:text-6xl'>
|
|
Start with the coaching context that matters.
|
|
</h1>
|
|
<p className='mt-5 max-w-xl text-lg leading-8 text-[#72798a]'>
|
|
Share what you want to work on. Your coach can review this, create
|
|
a client record, and prepare the first session around your goals.
|
|
</p>
|
|
</div>
|
|
|
|
<div className='rounded-none border border-[#19192d]/10 bg-white p-7'>
|
|
{isSubmitted ? (
|
|
<div className='rounded-none bg-[#fffdf9] p-7'>
|
|
<p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
|
|
Received
|
|
</p>
|
|
<h2 className='mt-3 text-2xl font-semibold'>
|
|
Thanks, we have your intake.
|
|
</h2>
|
|
<p className='mt-3 leading-7 text-[#72798a]'>
|
|
Your coach can now review it and create your client workspace.
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<form className='space-y-4' onSubmit={submitIntake}>
|
|
<div className='grid gap-6 md:grid-cols-2'>
|
|
<FieldLabel label='Name'>
|
|
<input
|
|
required
|
|
value={values.name}
|
|
onChange={(event) =>
|
|
updateValue('name', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
<FieldLabel label='Email'>
|
|
<input
|
|
required
|
|
type='email'
|
|
value={values.email}
|
|
onChange={(event) =>
|
|
updateValue('email', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
</div>
|
|
|
|
<div className='grid gap-6 md:grid-cols-2'>
|
|
<FieldLabel label='Company'>
|
|
<input
|
|
value={values.company}
|
|
onChange={(event) =>
|
|
updateValue('company', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
<FieldLabel label='Role'>
|
|
<input
|
|
value={values.role_title}
|
|
onChange={(event) =>
|
|
updateValue('role_title', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
</div>
|
|
|
|
<FieldLabel label='What do you want coaching to help with?'>
|
|
<textarea
|
|
required
|
|
rows={4}
|
|
value={values.goal}
|
|
onChange={(event) =>
|
|
updateValue('goal', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
|
|
<FieldLabel label='What feels stuck right now?'>
|
|
<textarea
|
|
rows={3}
|
|
value={values.challenge}
|
|
onChange={(event) =>
|
|
updateValue('challenge', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
|
|
<FieldLabel label='What would a useful first outcome look like?'>
|
|
<textarea
|
|
rows={3}
|
|
value={values.desired_outcome}
|
|
onChange={(event) =>
|
|
updateValue('desired_outcome', event.target.value)
|
|
}
|
|
className={fieldClass}
|
|
/>
|
|
</FieldLabel>
|
|
|
|
<label className='flex gap-3 rounded-none bg-[#fffdf9] p-6 text-sm leading-6 text-[#72798a]'>
|
|
<input
|
|
type='checkbox'
|
|
checked={values.consent_ai_notes}
|
|
onChange={(event) =>
|
|
updateValue('consent_ai_notes', event.target.checked)
|
|
}
|
|
className='mt-1'
|
|
/>
|
|
I am comfortable with AI-assisted summaries and prep notes
|
|
being used by the coach inside this workspace.
|
|
</label>
|
|
|
|
<button
|
|
type='submit'
|
|
disabled={isSubmitting}
|
|
className='rounded-none bg-[#35b7a5] px-5 py-2.5 text-sm font-semibold text-white disabled:opacity-50'
|
|
>
|
|
{isSubmitting ? 'Submitting...' : 'Send intake'}
|
|
</button>
|
|
</form>
|
|
)}
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</>
|
|
);
|
|
}
|
|
|
|
Intake.getLayout = function getLayout(page: React.ReactElement) {
|
|
return <LayoutGuest>{page}</LayoutGuest>;
|
|
};
|