/* ============================================================
WorkStay — Booking Flow (multi-step)
exports: BookingFlow
============================================================ */
const { useState: useStateBk } = React;
const STEPS = ['Dates', 'Work needs', 'Details', 'Confirm'];
function BookingFlow({ go, params = {} }) {
const { PROPERTIES, OPERATORS } = window.WS_DATA;
const p = PROPERTIES.find(x => x.id === params.id) || PROPERTIES[0];
const op = OPERATORS[p.operator];
const [step, setStep] = useStateBk(0);
const [months, setMonths] = useStateBk(3);
const [needs, setNeeds] = useStateBk(['Wired desk', 'Quiet after 8pm']);
const [done, setDone] = useStateBk(false);
const total = p.price * months + 240;
const next = () => { if (step < 3) setStep(step + 1); else setDone(true); };
const back = () => { if (step > 0) setStep(step - 1); else go('property', { id: p.id }); };
const toggleNeed = n => setNeeds(prev => prev.includes(n) ? prev.filter(x => x !== n) : [...prev, n]);
if (done) return ;
return (
{/* left: form */}
{/* mobile-only compact summary */}
{p.collection}
{p.name}
{p.city}
Total
${total.toLocaleString()}
{/* progress */}
{STEPS.map((s, i) => (
{i < step ? : i + 1}
{s}
{i < STEPS.length - 1 && }
))}
{step === 0 && }
{step === 1 && }
{step === 2 && }
{step === 3 && }
{step === 0 ? 'Back to stay' : 'Back'}
{step === 3 ? 'Confirm & reserve' : 'Continue'}
{/* right: cinematic summary rail */}
);
}
function StepHead({ eyebrow, title }) {
return
;
}
function StepDates({ p, months, setMonths }) {
return (
{[['Move in', 'Apr 12, 2026'], ['Move out', `Jul 12, 2026`]].map(([l, v]) => (
))}
Duration
{months} months
setMonths(+e.target.value)} className="ws-range" style={{ width: '100%' }} />
1 moLong-stay 12 mo
{months >= 3 &&
Long-stay rate applied — 12% off monthly
}
);
}
function StepNeeds({ needs, toggleNeed }) {
const opts = [
{ n: 'Wired desk', i: 'desk' }, { n: 'Quiet after 8pm', i: 'quiet' }, { n: 'Video-call room', i: 'video' },
{ n: '1 Gbps fiber', i: 'wifi' }, { n: 'Standing desk', i: 'ergo' }, { n: 'Power backup', i: 'power' },
{ n: 'Great light', i: 'light' }, { n: 'Espresso bar', i: 'coffee' },
];
return (
We’ll match the setup and flag anything the Operator should prep before you arrive.
{opts.map(o => {
const on = needs.includes(o.n);
return (
);
})}
);
}
function Field({ label, placeholder, span }) {
return (
);
}
function StepDetails() {
return (
);
}
function StepConfirm({ p, op, months, needs, total }) {
return (
Total due at confirmation
${total.toLocaleString()}
);
}
function SummaryRow({ label, value }) {
return (
{label}
{value}
);
}
function BookingConfirmed({ p, op, months, total, go }) {
return (
You’re in.
{op.name} is preparing {p.name} for your {months}-month stay. You’ll get a confirmation and workspace checklist by email.
Confirmation
WS-{p.id.slice(0, 3).toUpperCase()}-2026
Total
${total.toLocaleString()}
go('home')}>Back to home
go('explore')}>Explore more stays
);
}
Object.assign(window, { BookingFlow });