new-site/site/src/components/intake/steps/DOTIntakeStep.astro
justin c98ac9ae54 Fix DOT intake crash: null-safe photo ID element refs
Script crashed on 'Cannot read properties of null' because photo ID
elements are inside a hidden section. All element refs now use
optional chaining instead of non-null assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 15:31:15 -05:00

419 lines
25 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
// 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">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" 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>
<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 service slug from wizard element or state
const wizardEl = document.querySelector(".pw-wizard[data-service]");
const pageSlug = wizardEl?.getAttribute("data-service") || "";
const slugs: string[] = state.batch_slugs || [pageSlug || 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; });
}
}
// 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: 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 (elements may not exist if section is hidden)
const idBtn = document.getElementById("dot-id-btn");
const idInput = document.getElementById("dot-photo-id") as HTMLInputElement | null;
const idPreview = document.getElementById("dot-id-preview");
const idImg = document.getElementById("dot-id-img") as HTMLImageElement | null;
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);
}
if (idPreview) idPreview.hidden = false;
if (idBtn) idBtn.style.display = "none";
});
idRemove?.addEventListener("click", () => {
(window as any).__dotPhotoId = null;
if (idInput) idInput.value = "";
if (idPreview) idPreview.hidden = true;
if (idBtn) idBtn.style.display = "flex";
});
</script>