/* Human readable summary for customers and staff */
function buildNotesBlob(inputs, total, hours){
const sizeLabel = (HOME_SIZE_RANGES.find(r=>r.value===inputs.size)||{}).label || inputs.size;
const addOnList = ADDONS
.map(([k,label]) => ( (INCLUDED_ADDONS[inputs.type]||new Set()).has(k)
? `${label} (Included)`
: (inputs.addons[k] ? label : null)))
.filter(Boolean)
.join(", ") || "None";
const lines = [
`Quote: ${fmt(total)}`,
`Cleaning: ${inputs.type==="standard" ? "Standard" : inputs.type==="moveout" ? "Move in or out" : inputs.type==="postconstruction" ? "Post construction" : "Deep"}`,
`Size: ${sizeLabel}`,
`Beds: ${inputs.beds} | Baths: ${inputs.baths}`,
`Frequency: ${cap(inputs.frequency)}`,
`Pets: ${inputs.petLevel}`,
`Add-ons: ${addOnList}`,
inputs.contact.address1 || inputs.contact.city || inputs.contact.zip
? `Service address: ${[
inputs.contact.address1, inputs.contact.address2,
[inputs.contact.city, inputs.contact.state].filter(Boolean).join(", "),
inputs.contact.zip
].filter(Boolean).join(" • ")}`
: "",
inputs.contact.gateCode ? `Gate or access: ${inputs.contact.gateCode}` : "",
inputs.contact.notes ? `Client notes: ${inputs.contact.notes}` : "",
`Estimated labor hours ≈ ${hours.toFixed(1)}`
].filter(Boolean);
const plain = lines.join(" • ").slice(0, 1900);
const html = lines
.map(l => l.replace(/^([^:]+:)/, "$1"))
.join("
");
return { plain, html };
}
/* Build the calendar URL with robust field mapping */
function buildCalendarURL(base, inputs, total, hours){
const { plain, html } = buildNotesBlob(inputs, total, hours);
const url = new URL(base);
const p = url.searchParams;
// Contact prefill (unchanged)
const name = (inputs.contact.name||"").trim();
const parts = name.split(/\s+/);
const first = parts[0] || "";
const last = parts.slice(1).join(" ") || "";
if (first) p.set("first_name", first);
if (last) p.set("last_name", last);
if (inputs.contact.email) p.set("email", inputs.contact.email);
const phoneE164 = raw => {
const d = String(raw||"").replace(/\D/g,"");
if (d.length===10) return "+1"+d;
if (d.length===11 && d.startsWith("1")) return "+"+d;
return raw||"";
};
const ph = phoneE164(inputs.contact.phone);
if (ph){ p.set("phone", ph); p.set("phone_number", ph); }
// Location
const address = [
inputs.contact.address1||"",
inputs.contact.address2||"",
[inputs.contact.city||"", inputs.contact.state||""].filter(Boolean).join(", "),
inputs.contact.zip||""
].filter(Boolean).join(" • ");
if (address){
p.set("location", address);
p.set("address", address);
p.set("appointment_location", address);
}
// Helper
const writeBoth = (key, value) => {
if (value == null) return;
p.set(`custom_values[${key}]`, String(value));
p.set(key, String(value));
};
// Core hidden fields
writeBoth("service_summary", plain);
writeBoth("service_summary_html", html); // NEW: HTML-friendly version
writeBoth("quoted_price", total);
writeBoth("quoted_hours", hours.toFixed(1));
writeBoth("cleaning_type", inputs.type);
writeBoth("home_size", inputs.size);
writeBoth("beds", inputs.beds);
writeBoth("baths", inputs.baths);
writeBoth("frequency", inputs.frequency);
writeBoth("pet_level", inputs.petLevel);
const addonsSelected = Object.entries(inputs.addons || {})
.filter(([,v]) => v)
.map(([k]) => k)
.join(",");
writeBoth("addons_selected", addonsSelected);
// General description
p.set("appointment_description", plain);
p.set("description", plain);
p.set("notes", plain);
// UX
p.set("prefill","true");
p.set("step","1");
p.set("tt", String(Date.now()));
return url.toString();
}