115 lines
5.0 KiB
React
115 lines
5.0 KiB
React
/**
|
|
* StartStep — Screen 1 "Simple Start" (spec §4 / §5).
|
|
* Captures name, property address, mobile, email, contact method + consent.
|
|
* Consent is required before proceeding (spec §15 Privacy / §3 compliance).
|
|
*/
|
|
import React from 'react';
|
|
import { User, MapPin, Phone, Mail, Wand2 } from 'lucide-react';
|
|
import { useEstimateWizard } from '../../EstimateWizardContext';
|
|
|
|
const Field = ({ icon: Icon, label, children }) => (
|
|
<label className="block">
|
|
<span className="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1.5 flex items-center gap-1.5">
|
|
{Icon && <Icon size={15} className="text-amber-500" />} {label}
|
|
</span>
|
|
{children}
|
|
</label>
|
|
);
|
|
|
|
const inputCls =
|
|
'w-full rounded-xl border border-zinc-200 dark:border-white/10 bg-white dark:bg-zinc-900 px-3.5 py-2.5 ' +
|
|
'text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-amber-500';
|
|
|
|
const StartStep = () => {
|
|
const { inputs, setInput, prefillDemo } = useEstimateWizard();
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<button
|
|
type="button"
|
|
onClick={prefillDemo}
|
|
className="w-full flex items-center justify-center gap-2 rounded-xl border border-dashed border-amber-300 dark:border-amber-500/30 bg-amber-50 dark:bg-amber-500/10 px-3 py-2.5 text-sm font-medium text-amber-700 dark:text-amber-300 hover:border-amber-400"
|
|
>
|
|
<Wand2 size={15} /> Try a demo address (auto-fills every answer)
|
|
</button>
|
|
|
|
<Field icon={User} label="Name">
|
|
<input
|
|
className={inputCls}
|
|
placeholder="First and last name"
|
|
value={inputs.name}
|
|
onChange={(e) => setInput('name', e.target.value)}
|
|
autoComplete="name"
|
|
/>
|
|
</Field>
|
|
|
|
<Field icon={MapPin} label="Property address">
|
|
<input
|
|
className={inputCls}
|
|
placeholder="Street, city, state, ZIP"
|
|
value={inputs.address}
|
|
onChange={(e) => setInput('address', e.target.value)}
|
|
autoComplete="street-address"
|
|
/>
|
|
</Field>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<Field icon={Phone} label="Mobile number">
|
|
<input
|
|
className={inputCls}
|
|
placeholder="(555) 123-4567"
|
|
value={inputs.phone}
|
|
onChange={(e) => setInput('phone', e.target.value)}
|
|
autoComplete="tel"
|
|
inputMode="tel"
|
|
/>
|
|
</Field>
|
|
<Field icon={Mail} label="Email">
|
|
<input
|
|
className={inputCls}
|
|
placeholder="you@email.com"
|
|
value={inputs.email}
|
|
onChange={(e) => setInput('email', e.target.value)}
|
|
autoComplete="email"
|
|
inputMode="email"
|
|
/>
|
|
</Field>
|
|
</div>
|
|
|
|
<div>
|
|
<span className="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1.5 block">Best contact method?</span>
|
|
<div className="flex gap-2">
|
|
{['text', 'email', 'phone'].map((m) => (
|
|
<button
|
|
key={m}
|
|
type="button"
|
|
onClick={() => setInput('contactMethod', m)}
|
|
className={`flex-1 rounded-xl border px-3 py-2 text-sm font-medium capitalize transition-all
|
|
${inputs.contactMethod === m
|
|
? 'border-amber-500 bg-amber-50 dark:bg-amber-500/10 text-amber-700 dark:text-amber-300'
|
|
: 'border-zinc-200 dark:border-white/10 text-zinc-600 dark:text-zinc-300 hover:border-amber-400'}`}
|
|
>
|
|
{m}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<label className="flex items-start gap-2.5 rounded-xl bg-zinc-50 dark:bg-white/5 p-3.5 cursor-pointer">
|
|
<input
|
|
type="checkbox"
|
|
className="mt-0.5 h-4 w-4 accent-amber-500"
|
|
checked={inputs.consent}
|
|
onChange={(e) => setInput('consent', e.target.checked)}
|
|
/>
|
|
<span className="text-xs text-zinc-600 dark:text-zinc-400 leading-relaxed">
|
|
I agree to be contacted about my roof estimate and understand my address and any insurance
|
|
details I provide are used to generate this educational report. This is not a binding quote.
|
|
</span>
|
|
</label>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default StartStep;
|