Three upload methods: - Upload File: standard file picker - Camera / Scanner: uses capture attribute for camera on mobile or TWAIN/WIA scanner devices on desktop - QR Code: generates QR with current page URL so user can scan with phone and take a photo of their ID on mobile QR generated via api.qrserver.com (no library dependency). Remove button restores all upload options. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
500 lines
30 KiB
Text
500 lines
30 KiB
Text
---
|
||
// 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" hidden>
|
||
<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" hidden>
|
||
<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">0–2 vehicles ($76 gov fee)</option>
|
||
<option value="3-5">3–5 vehicles ($227 gov fee)</option>
|
||
<option value="6-20">6–20 vehicles ($452 gov fee)</option>
|
||
<option value="21-100">21–100 vehicles ($1,576 gov fee)</option>
|
||
<option value="101-1000">101–1,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" hidden>
|
||
<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" hidden>
|
||
<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>
|
||
<div id="dot-id-upload-options">
|
||
<div style="display:flex;flex-wrap:wrap;gap:8px;justify-content:center">
|
||
<button type="button" id="dot-id-btn" style="display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border:1px solid #d1d5db;border-radius:8px;cursor:pointer;color:#374151;font-size:13px;font-weight:500">
|
||
<svg style="width:20px;height:20px;color:#64748b" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"/></svg>
|
||
Upload File
|
||
</button>
|
||
<button type="button" id="dot-id-scan-btn" style="display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border:1px solid #d1d5db;border-radius:8px;cursor:pointer;color:#374151;font-size:13px;font-weight:500">
|
||
<svg style="width:20px;height:20px;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>
|
||
Camera / Scanner
|
||
</button>
|
||
</div>
|
||
<input type="file" id="dot-photo-id-scan" accept="image/*" capture="environment" style="display:none" />
|
||
<div style="text-align:center;margin:12px 0 0">
|
||
<div style="display:flex;align-items:center;gap:12px;justify-content:center;margin-bottom:8px">
|
||
<div style="flex:1;height:1px;background:#d1d5db"></div>
|
||
<span style="font-size:11px;color:#94a3b8;white-space:nowrap">or use your phone</span>
|
||
<div style="flex:1;height:1px;background:#d1d5db"></div>
|
||
</div>
|
||
<button type="button" id="dot-id-qr-btn" style="display:inline-flex;align-items:center;gap:8px;padding:8px 16px;background:#f8fafc;border:1px solid #d1d5db;border-radius:6px;cursor:pointer;font-size:12px;color:#374151">
|
||
<svg style="width:16px;height:16px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 4.875c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5A1.125 1.125 0 013.75 9.375v-4.5zM3.75 14.625c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5a1.125 1.125 0 01-1.125-1.125v-4.5zM13.5 4.875c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5A1.125 1.125 0 0113.5 9.375v-4.5z"/><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 6.75h.75v.75h-.75v-.75zM6.75 16.5h.75v.75h-.75v-.75zM16.5 6.75h.75v.75h-.75v-.75zM13.5 13.5h.75v.75h-.75v-.75zM13.5 19.5h.75v.75h-.75v-.75zM19.5 13.5h.75v.75h-.75v-.75zM19.5 19.5h.75v.75h-.75v-.75zM16.5 16.5h.75v.75h-.75v-.75z"/></svg>
|
||
Scan QR code to upload from phone
|
||
</button>
|
||
</div>
|
||
<div id="dot-id-qr-container" hidden style="text-align:center;margin:16px 0 0;padding:16px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px">
|
||
<canvas id="dot-id-qr-canvas" style="margin:0 auto;display:block"></canvas>
|
||
<p style="font-size:12px;color:#64748b;margin:10px 0 0">Scan this QR code with your phone's camera to open this form on your mobile device and take a photo of your ID.</p>
|
||
</div>
|
||
</div>
|
||
</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 is:inline>
|
||
// Guard: only run on pages that have the DOT intake step
|
||
if (!document.querySelector('[data-slug="dot-intake"], [data-step="dot-intake"]')) {
|
||
// Not a DOT intake page — skip all initialization
|
||
} else {
|
||
|
||
// Determine which sections to show based on services in the batch
|
||
const DOT_SECTIONS = {
|
||
"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).PWIntake;
|
||
const state = PW?.get?.() || {};
|
||
// Get service slug from wizard element or state
|
||
const wizardEl = document.querySelector(".pw-wizard[data-service]");
|
||
const pageSlug = wizardEl?.getAttribute("data-service") || "";
|
||
const slugs = state.batch_slugs || [pageSlug || state.service_slug || ""];
|
||
|
||
// Collect all sections to show
|
||
const show = new Set();
|
||
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");
|
||
const ucrState = document.getElementById("dot-ucr-state");
|
||
if (stateEl && ucrState) {
|
||
ucrState.value = stateEl.value;
|
||
stateEl.addEventListener("change", () => { ucrState.value = stateEl.value; });
|
||
}
|
||
}
|
||
|
||
// Show sections — retry until wizard element is found
|
||
function initSections() {
|
||
const wizardEl = document.querySelector(".pw-wizard[data-service]");
|
||
if (!wizardEl) { setTimeout(initSections, 100); return; }
|
||
showRelevantSections();
|
||
}
|
||
initSections();
|
||
window.addEventListener("pw:step-shown", (evt) => {
|
||
if (evt.detail.step !== "dot-intake") return;
|
||
showRelevantSections();
|
||
|
||
// Hydrate from existing intake data
|
||
const s = (window).PWIntake.get();
|
||
const d = s.intake_data || {};
|
||
const map = {
|
||
"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);
|
||
if (el && val) el.value = val;
|
||
}
|
||
});
|
||
|
||
// Save all data on step-next
|
||
window.addEventListener("pw:step-next", (evt) => {
|
||
const PW = (window).PWIntake;
|
||
if (PW.steps[PW.get().step_index] !== "dot-intake") return;
|
||
const errDiv = document.getElementById("pw-dot-errors");
|
||
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 = [];
|
||
for (const id of required) {
|
||
const el = document.getElementById(id);
|
||
if (!el || !el.value.trim()) missing.push(el?.parentElement?.querySelector("span")?.textContent || id);
|
||
}
|
||
// Validate visible-section-specific required fields
|
||
const visibleRequired = {
|
||
"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);
|
||
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 = [];
|
||
document.querySelectorAll("[data-cargo]").forEach(function(cb) {
|
||
if (cb.checked) cargoTypes.push(cb.dataset.cargo);
|
||
});
|
||
|
||
const val = (id) => (document.getElementById(id))?.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).__dotPhotoId,
|
||
}});
|
||
});
|
||
|
||
// Photo ID upload (elements may not exist if section is hidden)
|
||
const idBtn = document.getElementById("dot-id-btn");
|
||
const idInput = document.getElementById("dot-photo-id");
|
||
const idPreview = document.getElementById("dot-id-preview");
|
||
const idImg = document.getElementById("dot-id-img");
|
||
const idRemove = document.getElementById("dot-id-remove");
|
||
const idQrBtn = document.getElementById("dot-id-qr-btn");
|
||
const idQrContainer = document.getElementById("dot-id-qr-container");
|
||
const idUploadOpts = document.getElementById("dot-id-upload-options");
|
||
|
||
// Upload button — opens file picker
|
||
idBtn?.addEventListener("click", function() { if (idInput) idInput.click(); });
|
||
|
||
// Scanner/camera button — uses capture attribute to trigger camera or scanner
|
||
var idScanBtn = document.getElementById("dot-id-scan-btn");
|
||
var idScanInput = document.getElementById("dot-photo-id-scan");
|
||
idScanBtn?.addEventListener("click", function() { if (idScanInput) idScanInput.click(); });
|
||
idScanInput?.addEventListener("change", function() {
|
||
var file = idScanInput.files?.[0];
|
||
if (!file) return;
|
||
// Copy to main input handler
|
||
window.__dotPhotoId = file;
|
||
if (file.type.startsWith("image/") && idImg) {
|
||
var reader = new FileReader();
|
||
reader.onload = function(e) { idImg.src = e.target?.result; };
|
||
reader.readAsDataURL(file);
|
||
}
|
||
if (idPreview) idPreview.hidden = false;
|
||
if (idUploadOpts) idUploadOpts.style.display = "none";
|
||
});
|
||
|
||
// QR code button — show QR with current page URL for phone upload
|
||
idQrBtn?.addEventListener("click", function() {
|
||
if (!idQrContainer) return;
|
||
var showing = !idQrContainer.hidden;
|
||
idQrContainer.hidden = showing;
|
||
if (!showing) {
|
||
// Generate QR code using canvas
|
||
var canvas = document.getElementById("dot-id-qr-canvas");
|
||
if (canvas && !canvas.dataset.rendered) {
|
||
var url = window.location.href;
|
||
// Use a simple QR code API (Google Charts - no library needed)
|
||
var img = new Image();
|
||
img.crossOrigin = "anonymous";
|
||
img.onload = function() {
|
||
canvas.width = 200;
|
||
canvas.height = 200;
|
||
var ctx = canvas.getContext("2d");
|
||
ctx.drawImage(img, 0, 0, 200, 200);
|
||
canvas.dataset.rendered = "1";
|
||
};
|
||
img.src = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=" + encodeURIComponent(url);
|
||
}
|
||
}
|
||
});
|
||
|
||
idInput?.addEventListener("change", function() {
|
||
var file = idInput.files?.[0];
|
||
if (!file) return;
|
||
window.__dotPhotoId = file;
|
||
if (file.type.startsWith("image/")) {
|
||
const reader = new FileReader();
|
||
reader.onload = (e) => { idImg.src = e.target?.result; };
|
||
reader.readAsDataURL(file);
|
||
}
|
||
if (idPreview) idPreview.hidden = false;
|
||
if (idUploadOpts) idUploadOpts.style.display = "none";
|
||
});
|
||
idRemove?.addEventListener("click", () => {
|
||
(window).__dotPhotoId = null;
|
||
if (idInput) idInput.value = "";
|
||
if (idScanInput) idScanInput.value = "";
|
||
if (idPreview) idPreview.hidden = true;
|
||
if (idUploadOpts) idUploadOpts.style.display = "";
|
||
});
|
||
|
||
} // end guard
|
||
</script>
|