Unified DOT intake form — one form for all trucking services

Single DOTIntakeStep shows/hides sections based on services ordered:
- Company info + address + signer (always)
- Entity & operations (MCS-150, USDOT, MC Auth, bundles)
- Fleet info (MCS-150, UCR, bundles)
- UCR fleet bracket + base state (UCR)
- Cargo types (MCS-150, bundles)
- D&A program (CDL drivers, DER, consortium)
- BOC-3 docket info (BOC-3)
- Photo ID upload (MCS-150, MC Auth)
- Security/encryption notices

All DOT services now use ["dot-intake", "review"] instead of ["review"].

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
justin 2026-05-30 15:23:48 -05:00
parent 72d1b336c5
commit 8ce9e2e118
3 changed files with 423 additions and 11 deletions

View file

@ -40,6 +40,7 @@ import CPNIStep from "./steps/CPNIStep.astro";
import CDRPeriodStep from "./steps/CDRPeriodStep.astro";
import OCNStep from "./steps/OCNStep.astro";
import MCS150Step from "./steps/MCS150Step.astro";
import DOTIntakeStep from "./steps/DOTIntakeStep.astro";
import ClassificationWizard from "./steps/ClassificationWizard.astro";
import ReviewStep from "./steps/ReviewStep.astro";
import PaymentStep from "./steps/PaymentStep.astro";
@ -120,6 +121,7 @@ const STEP_LABELS: Record<string, string> = {
{steps.includes("cdr_period") && <div data-step="cdr_period" hidden><CDRPeriodStep /></div>}
{steps.includes("ocn") && <div data-step="ocn" hidden><OCNStep /></div>}
{steps.includes("mcs150") && <div data-step="mcs150" hidden><MCS150Step /></div>}
{steps.includes("dot-intake") && <div data-step="dot-intake" hidden><DOTIntakeStep /></div>}
{steps.includes("classification") && <div data-step="classification" hidden><ClassificationWizard /></div>}
{steps.includes("review") && <div data-step="review" hidden><ReviewStep service_slug={service_slug} /></div>}
{steps.includes("payment") && <div data-step="payment" hidden><PaymentStep service_slug={service_slug} /></div>}

View file

@ -0,0 +1,410 @@
---
// Unified DOT intake form — shows relevant sections based on services ordered.
// Handles: MCS-150, UCR, D&A, BOC-3, USDOT, MC Authority, Audit Prep, bundles.
---
<div class="pw-step" data-slug="dot-intake">
<h2>DOT Filing Information</h2>
<p class="pw-help">
Provide your carrier information. We will prepare and submit your filings on your behalf.
</p>
<div class="pw-security-notice">
<svg style="width:16px;height:16px;flex-shrink:0;margin-top:2px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/></svg>
<span>All personal information is transmitted over 256-bit SSL encryption and stored encrypted at rest. We never share your data with third parties.</span>
</div>
<div class="pw-form-grid">
<!-- ═══ SECTION: Company Info (always shown) ═══ -->
<h3>Company Information</h3>
<div class="pw-row">
<label class="pw-field"><span>Legal Entity Name <em>*</em></span>
<input type="text" id="dot-legal-name" required placeholder="As registered with FMCSA" /></label>
</div>
<div class="pw-row">
<label class="pw-field"><span>DBA / Trade Name</span>
<input type="text" id="dot-dba" placeholder="If different from legal name" /></label>
</div>
<div class="pw-row-3">
<label class="pw-field"><span>USDOT Number <em>*</em></span>
<input type="text" id="dot-dot" required placeholder="e.g. 1234567" /></label>
<label class="pw-field"><span>MC/MX/FF Number</span>
<input type="text" id="dot-mc" placeholder="e.g. MC-123456" /></label>
<label class="pw-field"><span>EIN (Tax ID)</span>
<input type="text" id="dot-ein" placeholder="XX-XXXXXXX" maxlength="12" /></label>
</div>
<h3>Principal Business Address</h3>
<div class="pw-row">
<label class="pw-field"><span>Street Address <em>*</em></span>
<input type="text" id="dot-street" required placeholder="123 Main St" /></label>
</div>
<div class="pw-row-3">
<label class="pw-field"><span>City <em>*</em></span>
<input type="text" id="dot-city" required /></label>
<label class="pw-field"><span>State <em>*</em></span>
<select id="dot-state" required>
<option value="">--</option>
<option value="AL">AL</option><option value="AK">AK</option><option value="AZ">AZ</option><option value="AR">AR</option><option value="CA">CA</option><option value="CO">CO</option><option value="CT">CT</option><option value="DE">DE</option><option value="FL">FL</option><option value="GA">GA</option><option value="HI">HI</option><option value="ID">ID</option><option value="IL">IL</option><option value="IN">IN</option><option value="IA">IA</option><option value="KS">KS</option><option value="KY">KY</option><option value="LA">LA</option><option value="ME">ME</option><option value="MD">MD</option><option value="MA">MA</option><option value="MI">MI</option><option value="MN">MN</option><option value="MS">MS</option><option value="MO">MO</option><option value="MT">MT</option><option value="NE">NE</option><option value="NV">NV</option><option value="NH">NH</option><option value="NJ">NJ</option><option value="NM">NM</option><option value="NY">NY</option><option value="NC">NC</option><option value="ND">ND</option><option value="OH">OH</option><option value="OK">OK</option><option value="OR">OR</option><option value="PA">PA</option><option value="RI">RI</option><option value="SC">SC</option><option value="SD">SD</option><option value="TN">TN</option><option value="TX">TX</option><option value="UT">UT</option><option value="VT">VT</option><option value="VA">VA</option><option value="WA">WA</option><option value="WV">WV</option><option value="WI">WI</option><option value="WY">WY</option><option value="DC">DC</option>
</select></label>
<label class="pw-field"><span>ZIP <em>*</em></span>
<input type="text" id="dot-zip" required maxlength="10" placeholder="12345" /></label>
</div>
<div class="pw-row-2">
<label class="pw-field"><span>Phone <em>*</em></span>
<input type="tel" id="dot-phone" required placeholder="(555) 123-4567" /></label>
<label class="pw-field"><span>Email <em>*</em></span>
<input type="email" id="dot-email" required placeholder="you@company.com" /></label>
</div>
<!-- ═══ SECTION: Entity & Operations (MCS-150, USDOT, MC Auth, bundles) ═══ -->
<div id="dot-sec-operations">
<h3>Entity & Operations</h3>
<div class="pw-row-2">
<label class="pw-field"><span>Entity Type <em>*</em></span>
<select id="dot-entity-type" required>
<option value="">Select...</option>
<option value="sole_proprietorship">Sole Proprietorship</option>
<option value="partnership">Partnership</option>
<option value="corporation">Corporation</option>
<option value="llc">LLC</option>
<option value="other">Other</option>
</select></label>
<label class="pw-field"><span>Carrier Operation <em>*</em></span>
<select id="dot-carrier-op" required>
<option value="">Select...</option>
<option value="authorized_for_hire">Authorized For-Hire</option>
<option value="exempt_for_hire">Exempt For-Hire</option>
<option value="private_property">Private (Property)</option>
<option value="private_passengers">Private (Passengers)</option>
</select></label>
</div>
<div class="pw-row-2">
<label class="pw-field"><span>Interstate / Intrastate <em>*</em></span>
<select id="dot-interstate" required>
<option value="">Select...</option>
<option value="interstate">Interstate (across state lines)</option>
<option value="intrastate_hazmat">Intrastate — Hazmat</option>
<option value="intrastate_non_hazmat">Intrastate — Non-hazmat</option>
</select></label>
<label class="pw-field"><span>Hazmat? <em>*</em></span>
<select id="dot-hazmat" required>
<option value="">Select...</option>
<option value="no">No</option>
<option value="yes">Yes</option>
</select></label>
</div>
</div>
<!-- ═══ SECTION: Fleet (MCS-150, UCR, bundles) ═══ -->
<div id="dot-sec-fleet">
<h3>Fleet Information</h3>
<div class="pw-row-3">
<label class="pw-field"><span>Power Units (trucks) <em>*</em></span>
<input type="number" id="dot-power-units" required min="0" placeholder="e.g. 5" /></label>
<label class="pw-field"><span>Drivers <em>*</em></span>
<input type="number" id="dot-drivers" required min="0" placeholder="e.g. 6" /></label>
<label class="pw-field"><span>Annual Miles</span>
<input type="number" id="dot-miles" min="0" placeholder="e.g. 250000" /></label>
</div>
</div>
<!-- ═══ SECTION: UCR Fleet Bracket (UCR only) ═══ -->
<div id="dot-sec-ucr" hidden>
<h3>UCR Registration</h3>
<p class="pw-field-help">UCR fees are based on the number of qualifying commercial motor vehicles (over 10,001 lbs GVWR, 10+ passengers, or placardable hazmat).</p>
<div class="pw-row-2">
<label class="pw-field"><span>Fleet Size Bracket <em>*</em></span>
<select id="dot-ucr-bracket">
<option value="">Select...</option>
<option value="0-2">02 vehicles ($76 gov fee)</option>
<option value="3-5">35 vehicles ($227 gov fee)</option>
<option value="6-20">620 vehicles ($452 gov fee)</option>
<option value="21-100">21100 vehicles ($1,576 gov fee)</option>
<option value="101-1000">1011,000 vehicles ($7,511 gov fee)</option>
<option value="1001+">1,001+ vehicles ($73,346 gov fee)</option>
</select></label>
<label class="pw-field"><span>Base State <em>*</em></span>
<input type="text" id="dot-ucr-state" readonly placeholder="From address above" /></label>
</div>
</div>
<!-- ═══ SECTION: Cargo Types (MCS-150, bundles) ═══ -->
<div id="dot-sec-cargo">
<h3>Cargo Types (check all that apply)</h3>
<div class="pw-cargo-grid">
<label><input type="checkbox" data-cargo="general" /> General Freight</label>
<label><input type="checkbox" data-cargo="household" /> Household Goods</label>
<label><input type="checkbox" data-cargo="metal" /> Metal/Sheets/Coils</label>
<label><input type="checkbox" data-cargo="motor_vehicles" /> Motor Vehicles</label>
<label><input type="checkbox" data-cargo="drivetow" /> Drive/Tow Away</label>
<label><input type="checkbox" data-cargo="logs" /> Logs/Poles/Lumber</label>
<label><input type="checkbox" data-cargo="building_materials" /> Building Materials</label>
<label><input type="checkbox" data-cargo="mobile_homes" /> Mobile Homes</label>
<label><input type="checkbox" data-cargo="machinery" /> Machinery/Large Objects</label>
<label><input type="checkbox" data-cargo="fresh_produce" /> Fresh Produce</label>
<label><input type="checkbox" data-cargo="liquids" /> Liquids/Gases</label>
<label><input type="checkbox" data-cargo="intermodal" /> Intermodal Containers</label>
<label><input type="checkbox" data-cargo="passengers" /> Passengers</label>
<label><input type="checkbox" data-cargo="oilfield" /> Oilfield Equipment</label>
<label><input type="checkbox" data-cargo="livestock" /> Livestock</label>
<label><input type="checkbox" data-cargo="grain" /> Grain/Feed/Hay</label>
<label><input type="checkbox" data-cargo="coal" /> Coal/Coke</label>
<label><input type="checkbox" data-cargo="meat" /> Meat</label>
<label><input type="checkbox" data-cargo="garbage" /> Garbage/Refuse</label>
<label><input type="checkbox" data-cargo="chemicals" /> Chemicals</label>
<label><input type="checkbox" data-cargo="refrigerated" /> Refrigerated Food</label>
<label><input type="checkbox" data-cargo="beverages" /> Beverages</label>
<label><input type="checkbox" data-cargo="construction" /> Construction</label>
<label><input type="checkbox" data-cargo="other" /> Other</label>
</div>
</div>
<!-- ═══ SECTION: D&A Program (D&A, bundles) ═══ -->
<div id="dot-sec-da" hidden>
<h3>Drug & Alcohol Compliance Program</h3>
<p class="pw-field-help">Required for all carriers with CDL drivers. We will enroll you in a DOT-compliant consortium and set up your program.</p>
<div class="pw-row-3">
<label class="pw-field"><span>CDL Drivers <em>*</em></span>
<input type="number" id="dot-cdl-drivers" min="0" placeholder="Number of CDL holders" /></label>
<label class="pw-field"><span>Owner-Operators <em>*</em></span>
<input type="number" id="dot-owner-ops" min="0" value="0" /></label>
<label class="pw-field"><span>DER Name</span>
<input type="text" id="dot-der-name" placeholder="Designated Employer Rep (optional)" /></label>
</div>
<div class="pw-row">
<label class="pw-field"><span>Current D&A Program Provider</span>
<input type="text" id="dot-current-da" placeholder="Leave blank if none / first time" /></label>
</div>
</div>
<!-- ═══ SECTION: BOC-3 (BOC-3, bundles) ═══ -->
<div id="dot-sec-boc3" hidden>
<h3>BOC-3 Process Agent</h3>
<p class="pw-field-help">We will designate a blanket process agent covering all 48 contiguous states + DC.</p>
<div class="pw-row-2">
<label class="pw-field"><span>Docket Type</span>
<select id="dot-docket-type">
<option value="">Select if applicable...</option>
<option value="MC">MC (Motor Carrier)</option>
<option value="FF">FF (Freight Forwarder)</option>
<option value="MX">MX (Mexican Carrier)</option>
</select></label>
<label class="pw-field"><span>Docket Number</span>
<input type="text" id="dot-docket-num" placeholder="e.g. 123456" /></label>
</div>
</div>
<!-- ═══ SECTION: Authorized Signer (always shown) ═══ -->
<h3>Authorized Signer</h3>
<div class="pw-row-2">
<label class="pw-field"><span>Full Name <em>*</em></span>
<input type="text" id="dot-signer-name" required placeholder="Owner or officer" /></label>
<label class="pw-field"><span>Title <em>*</em></span>
<input type="text" id="dot-signer-title" required placeholder="e.g. Owner, President" /></label>
</div>
<!-- ═══ SECTION: Photo ID (MCS-150, MC Auth) ═══ -->
<div id="dot-sec-photo-id">
<h3>Government-Issued Photo ID</h3>
<p class="pw-field-help">Required for FMCSA filings. Driver's license, passport, or state ID.</p>
<div class="pw-upload-area">
<input type="file" id="dot-photo-id" accept="image/*,.pdf" capture="environment" style="display:none" />
<div id="dot-id-preview" hidden style="display:flex;align-items:center;gap:12px;justify-content:center">
<img id="dot-id-img" style="max-width:200px;max-height:150px;border-radius:6px;border:1px solid #d1d5db" />
<button type="button" id="dot-id-remove" style="background:#fee2e2;color:#991b1b;border:none;padding:4px 12px;border-radius:4px;font-size:12px;cursor:pointer">Remove</button>
</div>
<button type="button" id="dot-id-btn" style="display:flex;flex-direction:column;align-items:center;gap:6px;margin:0 auto;padding:12px 24px;background:none;border:none;cursor:pointer;color:#374151;font-size:13px">
<svg style="width:24px;height:24px;color:#64748b" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z"/><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM18.75 10.5h.008v.008h-.008V10.5z"/></svg>
<span>Take Photo or Upload ID</span>
</button>
</div>
<div class="pw-security-notice" style="margin-top:8px">
<svg style="width:14px;height:14px;flex-shrink:0;margin-top:2px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/></svg>
<span style="font-size:11px">Your ID is encrypted in transit and at rest. Used only for FMCSA identity verification and automatically deleted after filing.</span>
</div>
</div>
</div>
<div id="pw-dot-errors" class="pw-err" hidden></div>
</div>
<style>
.pw-step h2 { margin: 0 0 0.5rem; color: #1a2744; }
.pw-step h3 { color: #1a2744; margin: 1.25rem 0 0.5rem; font-size: 0.95rem; border-bottom: 1px solid #e2e8f0; padding-bottom: 0.3rem; }
.pw-help { color: #64748b; font-size: 0.9rem; margin-bottom: 1rem; }
.pw-form-grid { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 1rem 1.25rem; }
.pw-row, .pw-row-2, .pw-row-3 { margin-bottom: 0.75rem; }
.pw-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.pw-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.75rem; }
.pw-field { display: flex; flex-direction: column; gap: 0.2rem; }
.pw-field span { font-size: 0.8rem; font-weight: 600; color: #374151; }
.pw-field em { color: #dc2626; font-style: normal; }
.pw-field input, .pw-field select { padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.85rem; }
.pw-field input:focus, .pw-field select:focus { outline: none; border-color: #f97316; box-shadow: 0 0 0 2px rgba(249,115,22,0.2); }
.pw-field-help { font-size: 0.8rem; color: #64748b; margin: 0 0 0.5rem; }
.pw-cargo-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.3rem 1rem; font-size: 0.85rem; color: #374151; }
.pw-cargo-grid label { display: flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.pw-security-notice { display: flex; gap: 8px; align-items: flex-start; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; padding: 10px 14px; margin-bottom: 1rem; font-size: 12px; color: #1e40af; line-height: 1.5; }
.pw-upload-area { border: 2px dashed #d1d5db; border-radius: 8px; padding: 1rem; text-align: center; }
.pw-err { color: #b91c1c; margin-top: 0.75rem; font-size: 0.9rem; background: #fee2e2; padding: 0.5rem 0.75rem; border-radius: 6px; }
@media (max-width: 640px) { .pw-row-2, .pw-row-3 { grid-template-columns: 1fr; } .pw-cargo-grid { grid-template-columns: 1fr 1fr; } }
</style>
<script>
// Determine which sections to show based on services in the batch
const DOT_SECTIONS: Record<string, string[]> = {
"mcs150-update": ["dot-sec-operations","dot-sec-fleet","dot-sec-cargo","dot-sec-photo-id"],
"ucr-registration": ["dot-sec-fleet","dot-sec-ucr"],
"dot-drug-alcohol": ["dot-sec-da"],
"boc3-filing": ["dot-sec-boc3"],
"dot-registration": ["dot-sec-operations"],
"mc-authority": ["dot-sec-operations","dot-sec-photo-id"],
"dot-audit-prep": ["dot-sec-operations","dot-sec-fleet","dot-sec-da"],
"dot-full-compliance": ["dot-sec-operations","dot-sec-fleet","dot-sec-cargo","dot-sec-ucr","dot-sec-da","dot-sec-boc3","dot-sec-photo-id"],
};
function showRelevantSections() {
const PW = (window as any).PWIntake;
const state = PW.get();
// Get all service slugs in this batch
const slugs: string[] = state.batch_slugs || [state.service_slug || ""];
// Collect all sections to show
const show = new Set<string>();
for (const slug of slugs) {
for (const sec of (DOT_SECTIONS[slug] || [])) {
show.add(sec);
}
}
// Default: always show operations + fleet if nothing specific
if (show.size === 0) {
show.add("dot-sec-operations");
show.add("dot-sec-fleet");
}
// Show/hide sections
for (const id of Object.keys(DOT_SECTIONS).flatMap(k => DOT_SECTIONS[k])) {
const el = document.getElementById(id);
if (el) el.hidden = !show.has(id);
}
// Auto-fill UCR base state from address
const stateEl = document.getElementById("dot-state") as HTMLSelectElement;
const ucrState = document.getElementById("dot-ucr-state") as HTMLInputElement;
if (stateEl && ucrState) {
ucrState.value = stateEl.value;
stateEl.addEventListener("change", () => { ucrState.value = stateEl.value; });
}
}
window.addEventListener("pw:step-shown", (evt: any) => {
if (evt.detail.step !== "dot-intake") return;
showRelevantSections();
// Hydrate from existing intake data
const s = (window as any).PWIntake.get();
const d = s.intake_data || {};
const map: Record<string, string> = {
"dot-legal-name": d.legal_name || "", "dot-dba": d.dba_name || "",
"dot-dot": d.dot_number || "", "dot-mc": d.mc_number || "", "dot-ein": d.ein || "",
"dot-street": d.address_street || "", "dot-city": d.address_city || "",
"dot-state": d.address_state || "", "dot-zip": d.address_zip || "",
"dot-phone": d.phone || "", "dot-email": d.email || s.email || "",
"dot-entity-type": d.entity_type || "", "dot-carrier-op": d.carrier_operation || "",
"dot-interstate": d.interstate_intrastate || "", "dot-hazmat": d.hazmat || "",
"dot-power-units": d.power_units || "", "dot-drivers": d.drivers || "",
"dot-miles": d.annual_miles || "", "dot-signer-name": d.signer_name || "",
"dot-signer-title": d.signer_title || "", "dot-cdl-drivers": d.cdl_drivers || "",
"dot-owner-ops": d.owner_operators || "0", "dot-der-name": d.der_name || "",
"dot-current-da": d.current_da_provider || "", "dot-ucr-bracket": d.fleet_size_bracket || "",
};
for (const [id, val] of Object.entries(map)) {
const el = document.getElementById(id) as HTMLInputElement | HTMLSelectElement;
if (el && val) el.value = val;
}
});
// Save all data on step-next
window.addEventListener("pw:step-next", (evt: any) => {
const PW = (window as any).PWIntake;
if (PW.steps[PW.get().step_index] !== "dot-intake") return;
const errDiv = document.getElementById("pw-dot-errors") as HTMLDivElement;
errDiv.hidden = true;
// Validate required fields (only visible ones)
const required = ["dot-legal-name","dot-dot","dot-street","dot-city","dot-state","dot-zip","dot-phone","dot-email","dot-signer-name","dot-signer-title"];
const missing: string[] = [];
for (const id of required) {
const el = document.getElementById(id) as HTMLInputElement;
if (!el || !el.value.trim()) missing.push(el?.parentElement?.querySelector("span")?.textContent || id);
}
// Validate visible-section-specific required fields
const visibleRequired: Record<string, string[]> = {
"dot-sec-operations": ["dot-entity-type","dot-carrier-op","dot-interstate","dot-hazmat"],
"dot-sec-fleet": ["dot-power-units","dot-drivers"],
};
for (const [secId, fields] of Object.entries(visibleRequired)) {
const sec = document.getElementById(secId);
if (sec && !sec.hidden) {
for (const id of fields) {
const el = document.getElementById(id) as HTMLInputElement;
if (!el || !el.value.trim()) missing.push(el?.parentElement?.querySelector("span")?.textContent || id);
}
}
}
if (missing.length) { evt.preventDefault(); errDiv.hidden = false; errDiv.textContent = "Please fill in: " + missing.join(", "); return; }
// Collect cargo types
const cargoTypes: string[] = [];
document.querySelectorAll<HTMLInputElement>("[data-cargo]").forEach(cb => {
if (cb.checked) cargoTypes.push(cb.dataset.cargo!);
});
const val = (id: string) => (document.getElementById(id) as HTMLInputElement)?.value?.trim() || "";
const state = PW.get();
PW.set({ ...state, intake_data: { ...state.intake_data,
legal_name: val("dot-legal-name"), dba_name: val("dot-dba"),
dot_number: val("dot-dot"), mc_number: val("dot-mc"), ein: val("dot-ein"),
address_street: val("dot-street"), address_city: val("dot-city"),
address_state: val("dot-state"), address_zip: val("dot-zip"),
phone: val("dot-phone"), email: val("dot-email"),
entity_type: val("dot-entity-type"), carrier_operation: val("dot-carrier-op"),
interstate_intrastate: val("dot-interstate"), hazmat: val("dot-hazmat"),
power_units: val("dot-power-units"), drivers: val("dot-drivers"),
annual_miles: val("dot-miles"), cargo_types: cargoTypes,
signer_name: val("dot-signer-name"), signer_title: val("dot-signer-title"),
fleet_size_bracket: val("dot-ucr-bracket"), base_state: val("dot-ucr-state"),
cdl_drivers: val("dot-cdl-drivers"), owner_operators: val("dot-owner-ops"),
der_name: val("dot-der-name"), current_da_provider: val("dot-current-da"),
docket_type: val("dot-docket-type"), docket_number: val("dot-docket-num"),
photo_id_uploaded: !!(window as any).__dotPhotoId,
}});
});
// Photo ID upload
const idBtn = document.getElementById("dot-id-btn")!;
const idInput = document.getElementById("dot-photo-id") as HTMLInputElement;
const idPreview = document.getElementById("dot-id-preview")!;
const idImg = document.getElementById("dot-id-img") as HTMLImageElement;
const idRemove = document.getElementById("dot-id-remove")!;
idBtn?.addEventListener("click", () => idInput?.click());
idInput?.addEventListener("change", () => {
const file = idInput.files?.[0];
if (!file) return;
(window as any).__dotPhotoId = file;
if (file.type.startsWith("image/")) {
const reader = new FileReader();
reader.onload = (e) => { idImg.src = e.target?.result as string; };
reader.readAsDataURL(file);
}
idPreview.hidden = false;
idBtn.style.display = "none";
});
idRemove?.addEventListener("click", () => {
(window as any).__dotPhotoId = null;
idInput.value = "";
idPreview.hidden = true;
idBtn.style.display = "flex";
});
</script>

View file

@ -35,7 +35,8 @@ export type IntakeStep =
| "cpni_questions" // NEW: CPNI certification questionnaire (sec 5-9)
| "cdr_period"
| "ocn"
| "mcs150" // MCS-150 biennial update form fields
| "mcs150" // MCS-150 biennial update form fields (standalone)
| "dot-intake" // Unified DOT intake — shows sections based on services ordered
| "review"
| "payment";
@ -103,16 +104,15 @@ export const INTAKE_MANIFEST: Record<string, IntakeStep[]> = {
],
// ── DOT / FMCSA Motor Carrier Services ──────────────────────────
// Review-only intake: DOT#, name, email already collected at checkout.
// Admin handles the filing using the info from the order.
"mcs150-update": ["mcs150", "review"],
"boc3-filing": ["review"],
"ucr-registration": ["review"],
"dot-registration": ["review"],
"mc-authority": ["review"],
"dot-drug-alcohol": ["review"],
"dot-audit-prep": ["review"],
"dot-full-compliance": ["review"],
// Unified DOT intake form — shows relevant sections based on service.
"mcs150-update": ["dot-intake", "review"],
"boc3-filing": ["dot-intake", "review"],
"ucr-registration": ["dot-intake", "review"],
"dot-registration": ["dot-intake", "review"],
"mc-authority": ["dot-intake", "review"],
"dot-drug-alcohol": ["dot-intake", "review"],
"dot-audit-prep": ["dot-intake", "review"],
"dot-full-compliance": ["dot-intake", "review"],
// ── State-Level Trucking Compliance ─────────────────────────────────
// Admin-assisted: info collected at checkout, no intake form needed.