Fix 3 bugs: BDC undo, JSON parse safety, price formatting

1. BDC Yes/No buttons now have "Change answer" undo — clicking
   Yes or No is reversible without re-running the check
2. intake_data JSON.parse wrapped in try/catch with error logging
   instead of silently returning empty object
3. All CTA price displays use .toFixed(2) for consistent formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
justin 2026-04-27 15:13:18 -05:00
parent a7d7fee154
commit 75ea2c5c6f
2 changed files with 49 additions and 26 deletions

View file

@ -1716,7 +1716,16 @@ async function sendComplianceIntakeEmail(
if (!customerEmail) return;
const firstName = customerName.split(" ")[0] || customerName;
const intake = orders[0].intake_data ? (typeof orders[0].intake_data === "string" ? JSON.parse(orders[0].intake_data as string) : orders[0].intake_data) as Record<string, unknown> : {};
let intake: Record<string, unknown> = {};
if (orders[0].intake_data) {
try {
intake = typeof orders[0].intake_data === "string"
? JSON.parse(orders[0].intake_data as string)
: orders[0].intake_data as Record<string, unknown>;
} catch (parseErr) {
console.error(`[checkout] intake_data JSON parse failed for ${orderId}:`, parseErr);
}
}
const entityName = (intake.entity_name as string) || customerName;
const frn = (intake.frn as string) || "";

View file

@ -506,27 +506,40 @@ import Base from "../../layouts/Base.astro";
// BDC button handlers
if (check.id === "bdc_filing" && status === "unknown") {
card.querySelector(".bdc-yes")?.addEventListener("click", () => {
check.status = "yellow";
const cy = colorMap.yellow;
card.className = `${cy.bg} ${cy.border} border rounded-xl p-4 flex items-start gap-3`;
card.innerHTML = `<div class="${cy.iconColor} mt-0.5 flex-shrink-0">${icons.yellow}</div>
<div class="flex-1">
<p class="font-semibold ${cy.textColor}">${check.label || check.id}</p>
${check.due_date ? `<p class="text-xs ${cy.textColor} opacity-75 mt-0.5">Due: ${check.due_date}</p>` : ""}
${check.detail ? `<p class="text-sm ${cy.textColor} mt-1">${check.detail}</p>` : ""}
</div>`;
function setBdcStatus(newStatus) {
check.status = newStatus;
const c = colorMap[newStatus];
card.className = `${c.bg} ${c.border} border rounded-xl p-4 flex items-start gap-3`;
if (newStatus === "yellow") {
card.innerHTML = `<div class="${c.iconColor} mt-0.5 flex-shrink-0">${icons.yellow}</div>
<div class="flex-1">
<p class="font-semibold ${c.textColor}">${check.label || check.id}</p>
<p class="text-sm ${c.textColor} mt-1">BDC filing required — you provide broadband service.</p>
<button class="bdc-undo text-xs underline ${c.textColor} mt-1 opacity-75">Change answer</button>
</div>`;
} else if (newStatus === "green") {
card.innerHTML = `<div class="${c.iconColor} mt-0.5 flex-shrink-0">${icons.green}</div>
<div class="flex-1">
<p class="font-semibold ${c.textColor}">${check.label || check.id}</p>
<p class="text-sm ${c.textColor} mt-1">Not applicable — no broadband service.</p>
<button class="bdc-undo text-xs underline ${c.textColor} mt-1 opacity-75">Change answer</button>
</div>`;
}
// Undo button re-renders the original card with Yes/No
card.querySelector(".bdc-undo")?.addEventListener("click", () => {
check.status = "unknown";
const cu = colorMap.unknown;
card.className = `${cu.bg} ${cu.border} border rounded-xl p-4 flex items-start gap-3`;
card.innerHTML = inner;
// Re-attach Yes/No handlers
card.querySelector(".bdc-yes")?.addEventListener("click", () => setBdcStatus("yellow"));
card.querySelector(".bdc-no")?.addEventListener("click", () => setBdcStatus("green"));
renderCta(lastData);
});
renderCta(lastData);
});
card.querySelector(".bdc-no")?.addEventListener("click", () => {
check.status = "green";
const cg = colorMap.green;
card.className = `${cg.bg} ${cg.border} border rounded-xl p-4 flex items-start gap-3`;
card.innerHTML = `<div class="${cg.iconColor} mt-0.5 flex-shrink-0">${icons.green}</div>
<div class="flex-1">
<p class="font-semibold ${cg.textColor}">${check.label || check.id}</p>
</div>`;
});
}
card.querySelector(".bdc-yes")?.addEventListener("click", () => setBdcStatus("yellow"));
card.querySelector(".bdc-no")?.addEventListener("click", () => setBdcStatus("green"));
}
checksContainer.appendChild(card);
@ -645,31 +658,32 @@ import Base from "../../layouts/Base.astro";
const totalRow = document.getElementById("total-row");
let discountHtml = "";
const fmt = (v) => v.toFixed(2);
if (pricedCount >= 2) {
const discount = Math.round(total * 0.15);
const final_ = total - discount;
discountHtml = `<div class="flex justify-between text-sm">
<span class="text-gray-600">Subtotal</span>
<span class="text-gray-600">$${total}</span>
<span class="text-gray-600">$${fmt(total)}</span>
</div>
<div class="flex justify-between text-sm text-green-600 font-medium">
<span>15% bundle discount</span>
<span>-$${discount}</span>
<span>-$${fmt(discount)}</span>
</div>
<div class="flex justify-between text-lg font-bold mt-1">
<span>Total</span>
<span>$${final_}</span>
<span>$${fmt(final_)}</span>
</div>`;
} else if (pricedCount === 1) {
discountHtml = `<div class="flex justify-between text-sm">
<span class="text-gray-600">Total</span>
<span class="font-semibold">$${total}</span>
<span class="font-semibold">$${fmt(total)}</span>
</div>
<p class="text-xs text-amber-600 mt-1">Add another service for 15% off</p>`;
} else {
discountHtml = `<div class="flex justify-between text-sm">
<span class="text-gray-600">Total</span>
<span class="font-semibold">$${total}</span>
<span class="font-semibold">$${fmt(total)}</span>
</div>`;
}