trucking wrap-up: close-out becomes a paid order + workflow

- Checker closing mode now pitches a done-for-you 'Trucking Wrap-Up' ($199)
  with a buy button to /order/dot-compliance?services=carrier-closeout, instead
  of a lead form. DIY checklist replaced by what's-included list.
- Entity dissolution offered as a paid add-on with the lawsuits/liens/judgments
  warning before dissolving.
- New catalog services: carrier-closeout ($199), entity-dissolution ($199).
- CarrierCloseoutHandler orchestrates the sequential shutdown workflow
  (final MCS-150 out-of-business, MC revoke, UCR cancel, IFTA/IRP + state
  closures; dissolution branch for the add-on) as admin-tracked tasks.
- Sell-your-trucks: single shared form with quick-cash / marketplace / both;
  name field is now a real first+last name (no corp-name prefill).
- tickets categories: add truck_sale_both, drop business_closeout (now an order).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
justin 2026-05-31 01:01:02 -05:00
parent 1e34707258
commit b25d1f5fd3
6 changed files with 202 additions and 105 deletions

View file

@ -1,7 +1,7 @@
-- Widen tickets.category to allow lead-capture categories posted by the DOT
-- compliance checker (insurance, business close-out, truck-sale routing).
-- The CHECK constraint previously only allowed the support-widget categories,
-- so these INSERTs failed with a 500.
-- Widen tickets.category to allow the lead-capture categories posted by the DOT
-- compliance checker (insurance quote + truck-sale routing). The CHECK constraint
-- previously only allowed the support-widget categories, so these INSERTs 500'd.
-- (Business close-out is handled as a paid order, not a ticket, so it's not here.)
ALTER TABLE tickets DROP CONSTRAINT IF EXISTS tickets_category_check;
@ -13,8 +13,8 @@ ALTER TABLE tickets ADD CONSTRAINT tickets_category_check CHECK (
'service_request',
'quote',
'insurance_lead',
'business_closeout',
'truck_sale_quickcash',
'truck_sale_marketplace'
'truck_sale_marketplace',
'truck_sale_both'
]::text[])
);

View file

@ -281,6 +281,18 @@ const COMPLIANCE_SERVICES: Record<
erpnext_item: "DOT-FULL-COMPLIANCE",
discountable: true,
},
"carrier-closeout": {
name: "Trucking Wrap-Up (USDOT Shutdown)",
price_cents: 19900, // $199 — final MCS-150 (out of business) + MC revoke + UCR cancel + state account closures
erpnext_item: "CARRIER-CLOSEOUT",
discountable: true,
},
"entity-dissolution": {
name: "Business Entity Dissolution (LLC/Corp)",
price_cents: 19900, // $199 add-on — LLC/Corp dissolution + final report; state filing fees billed separately
erpnext_item: "ENTITY-DISSOLUTION",
discountable: true,
},
// ── State-Level Trucking Compliance ──────────────────────────────────
"irp-registration": {
name: "IRP Registration Assistance",

View file

@ -7,7 +7,7 @@ const router = Router();
const VALID_CATEGORIES = [
"question", "support", "issue", "service_request", "quote",
"insurance_lead", "business_closeout", "truck_sale_quickcash", "truck_sale_marketplace",
"insurance_lead", "truck_sale_quickcash", "truck_sale_marketplace", "truck_sale_both",
] as const;
// POST /api/v1/tickets

View file

@ -53,6 +53,8 @@ from .state_trucking import StateTruckingHandler
# EIN application + virtual mailbox
from .ein_application import EINApplicationHandler
from .mailbox_setup import MailboxSetupHandler
# Carrier close-out / trucking wrap-up (shutdown) + entity dissolution
from .carrier_closeout import CarrierCloseoutHandler
SERVICE_HANDLERS: dict[str, type] = {
"flsa-audit": FLSAAuditHandler,
@ -112,6 +114,8 @@ SERVICE_HANDLERS: dict[str, type] = {
"emergency-temporary-authority": MCS150UpdateHandler, # ask.fmcsa.dot.gov type 308
"ein-application": EINApplicationHandler,
"virtual-mailbox": MailboxSetupHandler,
"carrier-closeout": CarrierCloseoutHandler, # trucking wrap-up / USDOT shutdown
"entity-dissolution": CarrierCloseoutHandler, # add-on, same handler (dissolution branch)
"annual-report-filing": MCS150UpdateHandler, # admin-assisted
"registered-agent": MCS150UpdateHandler, # admin-assisted (NWRA/CorpTools)
"entity-reinstatement": MCS150UpdateHandler, # admin-assisted

View file

@ -0,0 +1,89 @@
"""Carrier Close-Out — Trucking Wrap-Up workflow.
Done-for-you shutdown of a motor carrier. Orchestrates the sequential
wind-down as an admin-tracked workflow:
final MCS-150 (Out of Business) -> revoke MC authority -> cancel UCR ->
close IFTA/IRP + state accounts -> advise on insurance timing.
The `entity-dissolution` add-on (separate slug, same handler) dissolves the
LLC/Corp and files the final report gated on a no-outstanding-liabilities
attestation.
Intake data:
- entity_name / legal_name, dot_number, mc_number
- phy_state / state, operating_states
"""
from __future__ import annotations
import json
import logging
import os
LOG = logging.getLogger("workers.services.carrier_closeout")
class CarrierCloseoutHandler:
SERVICE_SLUG = "carrier-closeout"
async def process(self, order_data: dict) -> list[str]:
order_number = order_data.get("order_number", order_data.get("name", ""))
return self.handle(order_data, order_number)
def handle(self, order_data: dict, order_number: str) -> list[str]:
intake = order_data.get("intake_data") or {}
if isinstance(intake, str):
intake = json.loads(intake)
slug = order_data.get("service_slug", self.SERVICE_SLUG)
name = intake.get("entity_name") or intake.get("legal_name") or "Unknown carrier"
dot = intake.get("dot_number") or intake.get("usdot") or "N/A"
state = intake.get("phy_state") or intake.get("state") or "N/A"
LOG.info("[%s] Carrier close-out (%s) for %s (DOT %s)", order_number, slug, name, dot)
if slug == "entity-dissolution":
steps = [
"Confirm NO outstanding lawsuits, liens, or judgments before dissolving (client attestation).",
f"File Articles of Dissolution for {name} with the {state} Secretary of State.",
"File final state report / franchise tax return; close state tax accounts.",
"Notify IRS (final return, check the 'final' box); close the EIN if requested.",
]
title = f"Entity Dissolution — {name} ({state})"
else:
steps = [
f"File final MCS-150 marking carrier OUT OF BUSINESS — deactivate USDOT {dot}.",
"Submit voluntary revocation of operating authority (MC) to FMCSA.",
"Cancel UCR registration; confirm marked inactive (no next-year bill).",
"Close IFTA account, file final quarterly return, retire decals.",
f"Return IRP apportioned plates to base state ({state}); close the account.",
"Close state-level accounts/permits (CA MCP/CARB, OR weight-mile, NY HUT, KY KYU, etc.) per operating states.",
"Advise client on insurance cancellation timing (only AFTER authority is revoked).",
]
title = f"Trucking Wrap-Up (Shutdown) — {name} (DOT {dot})"
description = (
f"Carrier: {name}\nUSDOT: {dot}\nMC: {intake.get('mc_number', 'N/A')}\n"
f"Base state: {state}\nOperating states: {intake.get('operating_states', 'N/A')}\n\n"
"Sequential wind-down steps:\n"
+ "\n".join(f" {i + 1}. {s}" for i, s in enumerate(steps))
)
self._create_todo(order_number, intake, title, description, slug, priority="high")
return [f"Close-out workflow queued: {title}"]
def _create_todo(self, order_number, intake, title, description, slug, priority="normal"):
try:
import psycopg2
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
with conn.cursor() as cur:
cur.execute(
"""
INSERT INTO admin_todos (
title, category, priority, order_number, service_slug,
description, data, status
) VALUES (%s, %s, %s, %s, %s, %s, %s, 'pending')
""",
(title, "filing", priority, order_number, slug, description, json.dumps(intake)),
)
conn.commit()
conn.close()
except Exception as exc:
LOG.error("[%s] Failed to create close-out todo: %s", order_number, exc)

View file

@ -286,64 +286,59 @@ Send reset link
function buildCloseoutHtml(data) {
var state = data.phy_state || "";
var steps = [];
steps.push("<strong>File a final MCS-150</strong> marking your carrier &ldquo;Out of Business.&rdquo; This deactivates USDOT&nbsp;" + data.dot_number + " so biennial-update obligations and $1,000/day late penalties stop accruing.");
steps.push("<strong>Voluntarily revoke your operating authority (MC)</strong> with FMCSA so it isn&rsquo;t left active and billable after you stop running.");
steps.push("<strong>Cancel your UCR registration</strong> &mdash; don&rsquo;t just skip renewal; confirm you&rsquo;re marked inactive so you aren&rsquo;t billed next year.");
steps.push("<strong>Close your IFTA account</strong>, file a final quarterly return, and return or destroy your IFTA decals.");
steps.push("<strong>Return your IRP apportioned plates</strong>" + (state ? " to your base state (" + state + ")" : "") + " and close the account so registration fees stop.");
if (STATE_CLOSEOUT[state]) steps.push("<strong>State requirement:</strong> " + STATE_CLOSEOUT[state]);
steps.push("<strong>Cancel your insurance</strong> &mdash; but only <em>after</em> your authority is revoked, so FMCSA doesn&rsquo;t flag an insurance lapse on an active carrier.");
steps.push("<strong>Dissolve your LLC / corporation</strong> with the state and file a final tax return so you stop owing annual-report fees and franchise tax.");
var orderUrl = "/order/dot-compliance?dot=" + data.dot_number + "&services=carrier-closeout&intent=closing";
var includes = [];
includes.push("File your <strong>final MCS-150 (Out of Business)</strong> to deactivate USDOT&nbsp;" + data.dot_number + " &mdash; stops biennial-update obligations and $1,000/day late penalties.");
includes.push("<strong>Revoke your operating authority (MC)</strong> with FMCSA so it isn&rsquo;t left active and billable.");
includes.push("<strong>Cancel your UCR registration</strong> and confirm you&rsquo;re marked inactive so next year&rsquo;s bill never comes.");
includes.push("<strong>Close your IFTA account</strong>, file the final quarterly return, and handle your decals.");
includes.push("<strong>Return your IRP plates</strong>" + (state ? " to your base state (" + state + ")" : "") + " and close the account.");
if (STATE_CLOSEOUT[state]) includes.push("<strong>Close your state account:</strong> " + STATE_CLOSEOUT[state]);
includes.push("We tell you <strong>exactly when to cancel your insurance</strong> so FMCSA doesn&rsquo;t flag a lapse.");
var h = '';
// Intro
h += '<div style="background:#f0fdf4;border:2px solid #86efac;border-radius:12px;padding:24px;margin-top:8px">';
h += '<h3 style="font-size:18px;font-weight:700;color:#166534;margin:0 0 6px">Winding down ' + data.legal_name + '? Here&rsquo;s your exit checklist.</h3>';
h += '<p style="font-size:14px;color:#374151;margin:0 0 16px">Closing a trucking business is more than parking the truck. Skip a step and the bills &mdash; UCR, IRP, state permits, annual reports &mdash; keep coming. Here&rsquo;s what to wrap up, based on your FMCSA record:</p>';
h += '<ol style="margin:0;padding:0;list-style:none;counter-reset:step">';
steps.forEach(function(s) {
h += '<li style="display:flex;gap:12px;padding:10px 0;border-bottom:1px solid #dcfce7;font-size:14px;color:#374151;line-height:1.6">';
h += '<span style="flex-shrink:0;width:24px;height:24px;border-radius:50%;background:#16a34a;color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center;margin-top:1px">&#10003;</span>';
// Done-for-you trucking wrap-up service ($199)
h += '<div style="background:#f0fdf4;border:2px solid #16a34a;border-radius:12px;padding:24px;margin-top:8px">';
h += '<h3 style="font-size:19px;font-weight:800;color:#166534;margin:0 0 6px">Let us handle your entire trucking wrap-up</h3>';
h += '<p style="font-size:14px;color:#374151;margin:0 0 14px">Closing ' + data.legal_name + '? Don&rsquo;t leave loose ends that keep billing you after you&rsquo;re off the road. We do the whole shutdown for you &mdash; no Login.gov, no government portals:</p>';
h += '<ul style="margin:0 0 18px;padding:0;list-style:none">';
includes.forEach(function(s) {
h += '<li style="display:flex;gap:10px;padding:8px 0;border-bottom:1px solid #dcfce7;font-size:14px;color:#374151;line-height:1.6">';
h += '<span style="flex-shrink:0;width:22px;height:22px;border-radius:50%;background:#16a34a;color:#fff;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;margin-top:1px">&#10003;</span>';
h += '<span>' + s + '</span></li>';
});
h += '</ol></div>';
// "Let us handle it" lead capture (green)
h += '<div style="background:#fff;border:2px solid #16a34a;border-radius:12px;padding:24px;margin-top:8px">';
h += '<h3 style="font-size:17px;font-weight:700;color:#166534;margin:0 0 4px">Let us handle the shutdown paperwork</h3>';
h += '<p style="font-size:14px;color:#374151;margin:0 0 14px">We&rsquo;ll deactivate your USDOT, revoke your authority, cancel UCR, and close your state accounts &mdash; so nothing keeps billing you after you&rsquo;re out. No Login.gov, no government portals.</p>';
h += '<input type="text" id="co-name" placeholder="Your name" value="' + (data.legal_name || '') + '" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box">';
h += '<input type="email" id="co-email" placeholder="Email address" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box">';
h += '<input type="tel" id="co-phone" placeholder="Phone number" value="' + (data.telephone || '') + '" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:10px;box-sizing:border-box">';
h += '<button type="button" id="co-submit" style="padding:11px 28px;background:#16a34a;color:#fff;font-weight:700;border-radius:8px;font-size:14px;border:none;cursor:pointer">Get My Shutdown Handled &rarr;</button>';
h += '<p id="co-status" class="text-xs hidden" style="margin-top:8px"></p>';
h += '</ul>';
h += '<div style="display:flex;align-items:center;gap:16px;flex-wrap:wrap">';
h += '<a href="' + orderUrl + '" style="display:inline-block;padding:14px 34px;background:#16a34a;color:#fff;font-weight:800;border-radius:8px;text-decoration:none;font-size:16px;box-shadow:0 4px 12px rgba(22,163,74,0.3)">Start My Wrap-Up &mdash; $199 &rarr;</a>';
h += '<span style="font-size:13px;color:#15803d;font-weight:600">Flat $199. We file everything for you.</span>';
h += '</div>';
// Entity dissolution add-on + liability caveat
h += '<div style="margin-top:16px;padding-top:14px;border-top:1px solid #dcfce7">';
h += '<p style="font-size:13px;color:#374151;margin:0;line-height:1.6"><strong>Also closing the business entity?</strong> Add <strong>LLC/Corp dissolution + final report</strong> at checkout. <span style="color:#b91c1c">Don&rsquo;t dissolve if you have any outstanding lawsuits, liens, or judgments &mdash; settle those first; dissolving with open liabilities can put your personal assets at risk.</span></p>';
h += '</div>';
h += '</div>';
// Sell-your-trucks box (green)
// Sell-your-trucks box (green) — quick cash / marketplace / both, one shared form
var optStyle = "flex:1;min-width:180px;padding:14px;border-radius:10px;border:2px solid #86efac;background:#fff;color:#166534;font-weight:700;font-size:14px;cursor:pointer;text-align:left;line-height:1.4";
var subStyle = "font-weight:400;font-size:12px;color:#15803d";
var inStyle = "width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box";
h += '<div style="background:#f0fdf4;border:2px solid #86efac;border-radius:12px;padding:24px;margin-top:8px">';
h += '<h3 style="font-size:17px;font-weight:700;color:#166534;margin:0 0 4px">Looking to sell your trucks?</h3>';
h += '<p style="font-size:14px;color:#374151;margin:0 0 14px">Two ways to go &mdash; pick what fits your timeline:</p>';
h += '<p style="font-size:14px;color:#374151;margin:0 0 14px">Pick what fits your timeline &mdash; or do both and take the better deal:</p>';
h += '<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:4px">';
h += '<button type="button" class="sell-opt" data-opt="quickcash" style="flex:1;min-width:200px;padding:14px;border-radius:10px;border:2px solid #16a34a;background:#fff;color:#166534;font-weight:700;font-size:14px;cursor:pointer;text-align:left;line-height:1.4">&#128176; Quick cash now<br><span style="font-weight:400;font-size:12px;color:#15803d">Instant offer, pickup in 48&ndash;72 hrs</span></button>';
h += '<button type="button" class="sell-opt" data-opt="marketplace" style="flex:1;min-width:200px;padding:14px;border-radius:10px;border:2px solid #86efac;background:#fff;color:#166534;font-weight:700;font-size:14px;cursor:pointer;text-align:left;line-height:1.4">&#127991;&#65039; List it &amp; wait for top dollar<br><span style="font-weight:400;font-size:12px;color:#15803d">We&rsquo;ll send you the best marketplaces</span></button>';
h += '<button type="button" class="sell-opt" data-opt="quickcash" style="' + optStyle + '">&#128176; Quick cash now<br><span style="' + subStyle + '">Instant offer, pickup in 48&ndash;72 hrs</span></button>';
h += '<button type="button" class="sell-opt" data-opt="marketplace" style="' + optStyle + '">&#127991;&#65039; List &amp; wait for top dollar<br><span style="' + subStyle + '">We&rsquo;ll send the best marketplaces</span></button>';
h += '<button type="button" class="sell-opt" data-opt="both" style="' + optStyle + '">&#129309; Try both<br><span style="' + subStyle + '">A cash offer AND the listing guide</span></button>';
h += '</div>';
// Quick-cash form (hidden until chosen)
h += '<div id="sell-quickcash" style="display:none;margin-top:14px;padding-top:14px;border-top:1px solid #dcfce7">';
h += '<p style="font-size:13px;color:#374151;margin:0 0 10px">We&rsquo;ll connect you with a vetted truck-buying partner for a no-obligation cash offer. Tell us what you&rsquo;re selling:</p>';
h += '<input type="text" id="qc-name" placeholder="Your name" value="' + (data.legal_name || '') + '" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box">';
h += '<input type="tel" id="qc-phone" placeholder="Phone number" value="' + (data.telephone || '') + '" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box">';
h += '<input type="email" id="qc-email" placeholder="Email address" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:8px;box-sizing:border-box">';
h += '<textarea id="qc-truck" rows="2" placeholder="Year / make / model / mileage / condition" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:10px;box-sizing:border-box;resize:vertical"></textarea>';
h += '<button type="button" id="qc-submit" style="padding:11px 28px;background:#16a34a;color:#fff;font-weight:700;border-radius:8px;font-size:14px;border:none;cursor:pointer">Get My Cash Offer &rarr;</button>';
h += '<p id="qc-status" class="text-xs hidden" style="margin-top:8px"></p>';
h += '</div>';
// Marketplace form (hidden until chosen)
h += '<div id="sell-marketplace" style="display:none;margin-top:14px;padding-top:14px;border-top:1px solid #dcfce7">';
h += '<p style="font-size:13px;color:#374151;margin:0 0 10px">Smart move &mdash; a private/marketplace sale usually nets more than a quick buyout. Drop your email and we&rsquo;ll send you our guide to the top truck marketplaces and how to list for the best price.</p>';
h += '<input type="email" id="mp-email" placeholder="Email address" style="width:100%;padding:9px 12px;font-size:13px;border:1px solid #bbf7d0;border-radius:8px;outline:none;margin-bottom:10px;box-sizing:border-box">';
h += '<button type="button" id="mp-submit" style="padding:11px 28px;background:#16a34a;color:#fff;font-weight:700;border-radius:8px;font-size:14px;border:none;cursor:pointer">Email Me the Marketplace Guide &rarr;</button>';
h += '<p id="mp-status" class="text-xs hidden" style="margin-top:8px"></p>';
h += '<div id="sell-form" style="display:none;margin-top:14px;padding-top:14px;border-top:1px solid #dcfce7">';
h += '<p id="sell-intro" style="font-size:13px;color:#374151;margin:0 0 10px"></p>';
h += '<input type="text" id="sell-name" placeholder="Your first &amp; last name" style="' + inStyle + '">';
h += '<input type="tel" id="sell-phone" placeholder="Phone number" value="' + (data.telephone || '') + '" style="' + inStyle + '">';
h += '<input type="email" id="sell-email" placeholder="Email address" style="' + inStyle + '">';
h += '<textarea id="sell-truck" rows="2" placeholder="Year / make / model / mileage / condition" style="' + inStyle + 'resize:vertical;margin-bottom:10px"></textarea>';
h += '<button type="button" id="sell-submit" style="padding:11px 28px;background:#16a34a;color:#fff;font-weight:700;border-radius:8px;font-size:14px;border:none;cursor:pointer">Submit &rarr;</button>';
h += '<p id="sell-status" class="text-xs hidden" style="margin-top:8px"></p>';
h += '</div>';
h += '</div>';
@ -386,67 +381,64 @@ Send reset link
var loc = (data.phy_city || "") + ", " + (data.phy_state || "");
var fleet = data.fleet ? (data.fleet.power_units + " trucks, " + data.fleet.drivers + " drivers") : "unknown";
// "Handle my shutdown" lead
var coBtn = document.getElementById("co-submit");
if (coBtn) coBtn.addEventListener("click", function() {
var name = document.getElementById("co-name").value.trim();
var email = document.getElementById("co-email").value.trim();
var phone = document.getElementById("co-phone").value.trim();
pwSubmitLead({
category: "business_closeout", requireEmail: true, email: email, name: name,
btn: coBtn, statusEl: document.getElementById("co-status"),
okMsg: "Got it! We'll reach out within 1 business day to start your wind-down.",
subject: "Business Close-Out — " + data.legal_name + " (DOT " + data.dot_number + ")",
message: ["Business close-out / wind-down request from DOT Compliance Checker.", "",
"Carrier: " + data.legal_name, "DOT#: " + data.dot_number, "Location: " + loc, "Fleet: " + fleet,
"", "Contact: " + name, "Email: " + email, "Phone: " + (phone || data.telephone || "not provided")].join("\n")
});
});
var MODE = {
quickcash: {
intro: "We&rsquo;ll connect you with a vetted truck-buying partner for a no-obligation cash offer. Tell us what you&rsquo;re selling:",
truck: true, btn: "Get My Cash Offer &rarr;", category: "truck_sale_quickcash",
ok: "Got it — a truck buyer will reach out with a cash offer.", subj: "Truck Sale (Quick Cash)",
},
marketplace: {
intro: "Smart move — a private/marketplace sale usually nets more than a quick buyout. We&rsquo;ll email you our guide to the best truck marketplaces and how to list for top dollar.",
truck: false, btn: "Email Me the Marketplace Guide &rarr;", category: "truck_sale_marketplace",
ok: "Done! Watch your inbox for our truck-marketplace guide.", subj: "Truck Sale (Marketplace guide)",
},
both: {
intro: "Best of both — we&rsquo;ll line up a cash offer AND send you the marketplace guide so you can compare and take the better deal. Tell us what you&rsquo;re selling:",
truck: true, btn: "Get a Cash Offer + the Guide &rarr;", category: "truck_sale_both",
ok: "Done! We&rsquo;ll line up a cash offer and send the marketplace guide so you can compare.", subj: "Truck Sale (Both — cash offer + marketplace)",
},
};
// Sell-trucks option reveal
var current = null;
var form = document.getElementById("sell-form");
document.querySelectorAll(".sell-opt").forEach(function(b) {
b.addEventListener("click", function() {
var qc = document.getElementById("sell-quickcash");
var mp = document.getElementById("sell-marketplace");
qc.style.display = b.dataset.opt === "quickcash" ? "block" : "none";
mp.style.display = b.dataset.opt === "marketplace" ? "block" : "none";
current = b.dataset.opt;
var m = MODE[current];
if (form) form.style.display = "block";
document.getElementById("sell-intro").innerHTML = m.intro;
document.getElementById("sell-truck").style.display = m.truck ? "block" : "none";
document.getElementById("sell-submit").innerHTML = m.btn;
document.getElementById("sell-status").classList.add("hidden");
document.querySelectorAll(".sell-opt").forEach(function(x) {
x.style.background = x === b ? "#dcfce7" : "#fff";
});
});
});
// Quick-cash → truck-buyer referral lead
var qcBtn = document.getElementById("qc-submit");
if (qcBtn) qcBtn.addEventListener("click", function() {
var name = document.getElementById("qc-name").value.trim();
var phone = document.getElementById("qc-phone").value.trim();
var email = document.getElementById("qc-email").value.trim();
var truck = document.getElementById("qc-truck").value.trim();
var sBtn = document.getElementById("sell-submit");
if (sBtn) sBtn.addEventListener("click", function() {
if (!current) return;
var m = MODE[current];
var name = document.getElementById("sell-name").value.trim();
var phone = document.getElementById("sell-phone").value.trim();
var email = document.getElementById("sell-email").value.trim();
var truck = document.getElementById("sell-truck").value.trim();
var statusEl = document.getElementById("sell-status");
if (!name) {
statusEl.textContent = "Please enter your first & last name.";
statusEl.className = "text-xs text-red-600"; statusEl.classList.remove("hidden");
return;
}
pwSubmitLead({
category: "truck_sale_quickcash", requireEmail: false, email: email, name: name,
btn: qcBtn, statusEl: document.getElementById("qc-status"),
okMsg: "Got it — we'll connect you with a truck buyer who'll reach out with a cash offer.",
subject: "Truck Sale (Quick Cash) — " + data.legal_name + " (DOT " + data.dot_number + ")",
message: ["Quick-cash truck sale lead from DOT Compliance Checker — route to truck-buying partner.", "",
category: m.category, requireEmail: true, email: email, name: name,
btn: sBtn, statusEl: statusEl, okMsg: m.ok,
subject: m.subj + " — " + data.legal_name + " (DOT " + data.dot_number + ")",
message: [m.subj + " lead from DOT Compliance Checker.", "",
"Carrier: " + data.legal_name, "DOT#: " + data.dot_number, "Location: " + loc, "Fleet: " + fleet,
"Vehicle(s): " + (truck || "not specified"), "",
"Contact: " + name, "Email: " + email, "Phone: " + (phone || data.telephone || "not provided")].join("\n")
});
});
// Marketplace → guide follow-up lead
var mpBtn = document.getElementById("mp-submit");
if (mpBtn) mpBtn.addEventListener("click", function() {
var email = document.getElementById("mp-email").value.trim();
pwSubmitLead({
category: "truck_sale_marketplace", requireEmail: true, email: email, name: data.legal_name,
btn: mpBtn, statusEl: document.getElementById("mp-status"),
okMsg: "Done! Watch your inbox for our truck-marketplace guide.",
subject: "Truck Sale (Marketplace guide) — " + data.legal_name + " (DOT " + data.dot_number + ")",
message: ["Marketplace truck-sale lead from DOT Compliance Checker — send marketplace guide follow-up.", "",
"Carrier: " + data.legal_name, "DOT#: " + data.dot_number, "Location: " + loc, "Fleet: " + fleet,
"", "Email: " + email].join("\n")
(m.truck ? "Vehicle(s): " + (truck || "not specified") : null), "",
"Contact: " + name, "Email: " + email, "Phone: " + (phone || data.telephone || "not provided")]
.filter(function(x) { return x !== null; }).join("\n"),
});
});
}