Pre-Trip Inspection
Independent Freight Operators Group
--:--
📋 Inspection
🔧 Maintenance
🚨 Incident
🕐 History
Inspection Progress 0 / 0 items
Driver & Vehicle Info
Required
Defect Notes
Optional
Photo & Video Evidence
REC0:00

Camera inactive

Maintenance Log

No maintenance entries yet.
Tap Add Entry to log a repair or service.

Report History

No submitted reports yet.

Incident Report

No incident reports yet.
Tap New Report to file an accident or damage report.

Defect Report
Item
⚠️ Safety Risk
Check if this defect creates an immediate safety hazard
Safety Risk Flagged — Vehicle should NOT be operated until this defect is repaired. Notify dispatch immediately.
Receipt
IFROG
Install IFROG Inspection
Add to home screen - works offline, no app store
Running as App
`; const blob=new Blob([html],{type:'text/html'}); const url=URL.createObjectURL(blob); const a=document.createElement('a'); a.href=url; a.download='IFROG_maintenance_'+driverName.replace(/\s+/g,'_')+'_'+date+'.html'; a.click(); URL.revokeObjectURL(url); showToast('Maintenance log downloaded — save to OneDrive or share','ok'); } function downloadIncidentReport(){ const desc=document.getElementById('inc-description').value.trim(); if(!desc){showToast('Add a description first','error');return;} const driverName=document.getElementById('driver-name').value.trim()||'Unknown Driver'; const truck=document.getElementById('truck-num').value.trim(); const trailer=document.getElementById('trailer-num').value.trim(); const type=document.getElementById('inc-type').value; const date=document.getElementById('inc-date').value; const time=document.getElementById('inc-time').value; const location=document.getElementById('inc-location').value.trim(); const damage=document.getElementById('inc-damage').value.trim(); const parties=document.getElementById('inc-parties').value.trim(); const witnesses=document.getElementById('inc-witnesses').value.trim(); const actions=document.getElementById('inc-actions').value.trim(); const reportNum=document.getElementById('inc-report-num').value.trim(); const odo=document.getElementById('inc-odo').value; const typeLabels={accident:'Accident / Collision',damage:'Equipment Damage',cargo:'Cargo Damage / Loss',theft:'Theft / Vandalism',injury:'Personal Injury',near_miss:'Near Miss',other:'Other'}; const sevColor={minor:'#f59e0b',moderate:'#f97316',major:'#ef4444'}; const sevLabel={minor:'Minor',moderate:'Moderate',major:'Major'}; const sc=sevColor[currentIncidentSeverity]||'#ef4444'; const photos=currentIncidentMedia.filter(m=>m.type==='photo'); const videos=currentIncidentMedia.filter(m=>m.type==='video'); const html=`IFROG Incident Report
IFROG
Independent Freight Operators Group
Incident Report
${(typeLabels[type]||type).toUpperCase()}
${(sevLabel[currentIncidentSeverity]||'').toUpperCase()} SEVERITY${incidentInjuries?' · 🏥 INJURIES':''}
${[['Driver',driverName],['Date',date||'—'],['Time',time||'—'],['Truck #',truck||'—'],['Trailer #',trailer||'—'],['Odometer',odo?parseInt(odo).toLocaleString()+' mi':'—']].map(([l,v])=>`
${l}
${v}
`).join('')}
${location?`
📍 Location
${location}
`:''}
What Happened
${desc}
${damage?`
Damage / Injuries
${damage}
`:''} ${parties?`
Other Parties
${parties}
`:''} ${witnesses?`
Witnesses
${witnesses}
`:''} ${incidentPolice?`
🚔 Police / DOT Report Filed${reportNum?' — Case #'+reportNum:''}
`:''} ${actions?`
Immediate Actions Taken
${actions}
`:''} ${photos.length>0?`
Scene Photos (${photos.length})
${photos.map((m,i)=>`
Scene Photo ${i+1}
`).join('')}
`:''} ${videos.length>0?`
Video Clips Attached (${videos.length})
${videos.map(v=>v.name).join(', ')}
`:''}
Generated ${new Date().toLocaleString()} · IFROG Incident Report
`; const blob=new Blob([html],{type:'text/html'}); const url=URL.createObjectURL(blob); const a=document.createElement('a'); a.href=url; a.download='IFROG_incident_'+driverName.replace(/\s+/g,'_')+'_'+date+'.html'; a.click(); URL.revokeObjectURL(url); showToast('Incident report downloaded — save to OneDrive or share','ok'); } function submitInspection(){ const email=document.getElementById('report-email').value.trim(); if(!email){showToast('Please enter a report email address','error');return;} const driverName=document.getElementById('driver-name').value.trim()||'Unknown Driver'; const cdl=document.getElementById('driver-cdl').value.trim(); const truck=document.getElementById('truck-num').value.trim(); const trailer=document.getElementById('trailer-num').value.trim(); const odometer=document.getElementById('odometer').value.trim(); const date=document.getElementById('insp-date').value; const defects=document.getElementById('defects-notes').value.trim(); const all=Object.entries(state); const pass=all.filter(([,v])=>v.status==='pass').length, fail=all.filter(([,v])=>v.status==='fail').length; const na=all.filter(([,v])=>v.status==='na').length, pending=all.filter(([,v])=>v.status===null).length; const statusIcon=fail>0?'DEFECTS FOUND':pending>0?'INCOMPLETE':'PASSED'; let body='IFROG PRE-TRIP INSPECTION REPORT\n==================================\n\n'; body+='Status: '+statusIcon+'\nDate: '+date+'\nDriver: '+driverName+(cdl?' | CDL: '+cdl:'')+'\n'; body+='Truck: '+(truck||'N/A')+' | Trailer: '+(trailer||'N/A')+'\nOdometer: '+(odometer?odometer+' mi':'N/A')+'\n\n'; body+='RESULTS: '+pass+' Pass | '+fail+' Fail | '+na+' N/A | '+pending+' Pending / '+all.length+' Total\n\n'; SECTIONS.forEach(sec=>{ body+='--- '+sec.title.toUpperCase()+' ---\n'; sec.items.forEach(item=>{ const s=state[item.id]; const prefix=s.status==='pass'?'[PASS] ':s.status==='fail'?'[FAIL] ':s.status==='na'?'[N/A] ':'[----] '; body+=prefix+item.label+'\n'; if(s.status==='fail'&&s.failDetail){ body+=' Problem: '+s.failDetail.whatsWrong+'\n'; if(s.failDetail.whatsNeeded) body+=' Needed: '+s.failDetail.whatsNeeded+'\n'; if(s.failDetail.actionTaken) body+=' Action: '+s.failDetail.actionTaken+'\n'; body+=' Severity: '+({low:'Minor',med:'Moderate',high:'Critical'}[s.failDetail.severity]||'Unknown')+(s.failDetail.safetyRisk?' | ⚠️ SAFETY RISK':'')+'\n'; } }); body+='\n'; }); if(defects) body+='DEFECT NOTES:\n'+defects+'\n\n'; const photos=mediaFiles.filter(f=>f&&f.type==='photo').length, videos=mediaFiles.filter(f=>f&&f.type==='video').length; body+='MEDIA: '+photos+' photo(s), '+videos+' video(s) — see attached HTML report\n'; body+='\nIndependent Freight Operators Group\n'; const subject='IFROG Pre-Trip — '+driverName+' — Unit '+(truck||'N/A')+' — '+date; saveLastReport(); saveToHistory({driver:driverName,cdl,truck,trailer,odometer,date,defects,pass,fail,na,pending,total:all.length}); generateHTMLReport(driverName,cdl,truck,trailer,odometer,date,defects,pass,fail,na,pending,all.length); window.location.href='mailto:'+email+'?subject='+encodeURIComponent(subject)+'&body='+encodeURIComponent(body); showToast('Report submitted — HTML downloaded','ok'); } function generateHTMLReport(driverName,cdl,truck,trailer,odometer,date,defects,pass,fail,na,pending,total){ const sc=fail>0?'#ef4444':pending>0?'#8dc63f':'#4aad5a'; const sl=fail>0?'DEFECTS FOUND':pending>0?'INCOMPLETE':'PASSED'; const activeMF=mediaFiles.filter(Boolean); const sectHTML=SECTIONS.map(sec=>{ const rows=sec.items.map(item=>{ const s=state[item.id]; const c=s.status==='pass'?'#4aad5a':s.status==='fail'?'#ef4444':s.status==='na'?'#6b9e6b':'#f59e0b'; const lbl=s.status?s.status.toUpperCase():'—'; const sevColor={low:'#f59e0b',med:'#f97316',high:'#ef4444'}; const sevLabel={low:'Minor',med:'Moderate',high:'Critical'}; let failDetail=''; if(s.status==='fail'&&s.failDetail){ const fd=s.failDetail; failDetail=`
${fd.safetyRisk?'
⚠️ SAFETY RISK — DO NOT OPERATE
':''}
Problem:${fd.whatsWrong} ${fd.whatsNeeded?'Needed:'+fd.whatsNeeded+'':''} ${fd.actionTaken?'Action:'+fd.actionTaken+'':''} Severity:${sevLabel[fd.severity]||'—'}
`; } return `
${item.label}
${failDetail} ${item.note} ${lbl}`; }).join(''); const hasFails=sec.items.some(i=>state[i.id].status==='fail'); return '

'+sec.title+(hasFails?' ⚠':'')+'

'+rows+'
Item / Defect DetailGuidanceStatus
'; }).join(''); // Defect summary block const allFails = []; SECTIONS.forEach(sec=>sec.items.forEach(item=>{if(state[item.id].status==='fail')allFails.push({label:item.label,detail:state[item.id].failDetail});})); const defectSummaryHTML = allFails.length>0?`
⚠ Defect Summary — ${allFails.length} Item${allFails.length>1?'s':''} Failed
${allFails.map((f,i)=>`
${f.detail?.safetyRisk?'🚨':f.detail?.severity==='high'?'🔴':f.detail?.severity==='med'?'🟠':'🟡'}
${f.label}
${f.detail?`
${f.detail.whatsWrong}${f.detail.safetyRisk?' — SAFETY RISK':''}
`:''}
`).join('')}
`:''; const mHTML=maintEntries.length>0?'

Recent Maintenance

'+maintEntries.slice(0,5).map(e=>'
'+e.type+' · '+e.date+'
'+e.desc+'
'+(e.by?'
By: '+e.by+'
':'')+(e.cost?'
Cost: $'+parseFloat(e.cost).toFixed(2)+'
':'')+'
').join(''):''; const mediaHTML=activeMF.length>0?'

Media Evidence

'+activeMF.map(f=>f.type==='photo'?'

'+f.name+'

':'

'+f.name+'

').join('')+'
':''; const logoTag='IFROG'; const html='IFROG Pre-Trip Inspection
'+logoTag+'
Independent Freight Operators Group
Pre-Trip Inspection
'+sl+'
'+[['Driver',driverName],['CDL #',cdl||'—'],['Date',date],['Truck #',truck||'—'],['Trailer #',trailer||'—'],['Odometer',odometer?odometer+' mi':'—']].map(([l,v])=>'
'+l+'
'+v+'
').join('')+'
'+[['Pass','#4aad5a',pass],['Fail','#ef4444',fail],['N/A','#6b9e6b',na],['Pending','#8dc63f',pending]].map(([l,c,v])=>'
'+v+'
'+l+'
').join('')+'
'+defectSummaryHTML+sectHTML+(defects?'
Defect Notes

'+defects+'

':'')+mHTML+mediaHTML+'
Generated '+new Date().toLocaleString()+' · IFROG CDL Pre-Trip Inspection
'; const blob=new Blob([html],{type:'text/html'}); const url=URL.createObjectURL(blob); const a=document.createElement('a'); a.href=url; a.download='IFROG_inspection_'+driverName.replace(/\s+/g,'_')+'_'+date+'.html'; a.click(); URL.revokeObjectURL(url); } let toastTimer; function showToast(msg,type){ const el=document.getElementById('toast'); el.textContent=msg; el.className='toast'+(type==='error'?' error':'')+' show'; clearTimeout(toastTimer); toastTimer=setTimeout(()=>el.classList.remove('show'),3500); }