webapp1 commited on
Commit
c242b8e
·
verified ·
1 Parent(s): 3401182

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +83 -120
templates/index.html CHANGED
@@ -156,7 +156,6 @@
156
  <h1 class="text-4xl font-black tracking-tight text-indigo-950 dark:text-white drop-shadow-sm">CrashVision AI</h1>
157
  <p class="text-xs font-black uppercase tracking-[0.3em] text-indigo-500 mt-3">Initializing Systems</p>
158
 
159
- <!-- Loading Animation with Jiggle Physics -->
160
  <div class="mt-8 flex gap-3">
161
  <div class="w-3 h-3 rounded-md bg-fuchsia-500 animate-jiggle" style="animation-delay: 0s;"></div>
162
  <div class="w-3 h-3 rounded-md bg-indigo-500 animate-jiggle" style="animation-delay: 0.15s;"></div>
@@ -317,10 +316,8 @@
317
 
318
  <!-- Interactive Media Player Area -->
319
  <div class="rounded-[32px] overflow-hidden shadow-2xl border border-white/50 dark:border-white/20 relative bg-black aspect-video flex items-center justify-center group">
320
- <!-- Display Image (AI Overlays) -->
321
- <img id="previewImg" src="" class="w-full h-full object-contain z-10 hidden" alt="Detection View">
322
- <!-- Raw Video Feed Image -->
323
- <img id="rawFeedImg" src="" class="w-full h-full object-contain z-10 hidden" alt="Raw View">
324
 
325
  <!-- Snapshot Container Overlay -->
326
  <div id="snapshotContainer" class="absolute inset-0 z-30 hidden bg-black flex items-center justify-center">
@@ -367,17 +364,17 @@
367
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
368
  <i class="fas fa-location-dot text-rose-500 text-lg sm:text-xl mb-1 sm:mb-2"></i>
369
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Location</p>
370
- <p id="vLoc" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center px-1 break-words"></p>
371
  </div>
372
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
373
  <i class="fas fa-cloud-bolt text-cyan-500 text-lg sm:text-xl mb-1 sm:mb-2"></i>
374
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Conditions</p>
375
- <p id="vWx" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center break-words"></p>
376
  </div>
377
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
378
  <i class="fas fa-stopwatch text-indigo-500 dark:text-purple-300 text-lg sm:text-xl mb-1 sm:mb-2"></i>
379
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Timeline</p>
380
- <p id="vTime" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center break-words"></p>
381
  </div>
382
  </div>
383
  </div>
@@ -584,7 +581,7 @@
584
  </div>
585
  <div>
586
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Speed Limit</label>
587
- <input type="number" id="tab_speed" value="60" min="10" max="250" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 shadow-sm">
588
  </div>
589
  </div>
590
  </div>
@@ -600,11 +597,11 @@
600
  <div class="space-y-4">
601
  <div>
602
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Density (0-5)</label>
603
- <input type="number" id="tab_density" value="2" min="0" max="5" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
604
  </div>
605
  <div>
606
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicles Inv.</label>
607
- <input type="number" id="tab_vehicles" value="2" min="1" max="20" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
608
  </div>
609
  <div>
610
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicle Type</label>
@@ -629,15 +626,18 @@
629
  <div class="space-y-4">
630
  <div>
631
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Driver Age</label>
632
- <input type="number" id="tab_age" value="35" min="16" max="99" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
633
  </div>
634
  <div>
635
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Experience (Yrs)</label>
636
- <input type="number" id="tab_exp" value="10" min="0" max="80" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
637
  </div>
638
  <div>
639
- <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Alcohol Lvl (0-1)</label>
640
- <input type="number" id="tab_alcohol" value="0.0" step="0.1" min="0" max="1" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
 
 
 
641
  </div>
642
  </div>
643
  </div>
@@ -665,8 +665,8 @@
665
  <span id="riskLabelText">Low Risk</span>
666
  </div>
667
 
668
- <h4 class="text-7xl font-black tracking-tighter text-indigo-950 dark:text-white mb-2 drop-shadow-sm"><span id="riskProbabilityValue">0</span>%</h4>
669
- <p class="text-indigo-800/60 dark:text-purple-200 text-[10px] font-black uppercase tracking-widest mt-4">Calculated Accident Probability</p>
670
  </div>
671
 
672
  <div class="flex gap-4 max-w-sm w-full mt-4">
@@ -689,7 +689,6 @@
689
  const themeToggleBtn = document.getElementById('themeToggle');
690
  const htmlElement = document.documentElement;
691
 
692
- // Force light mode by default on first visit. Only switch if explicitly saved.
693
  if (localStorage.theme === 'dark') {
694
  htmlElement.classList.add('dark');
695
  } else {
@@ -706,7 +705,6 @@
706
  }
707
  });
708
 
709
- // App Splash Screen Removal Logic
710
  window.addEventListener('load', () => {
711
  setTimeout(() => {
712
  const splash = document.getElementById('appSplashScreen');
@@ -720,43 +718,6 @@
720
  }, 1800);
721
  });
722
 
723
- let currentLocationStr = "Unknown Location";
724
-
725
- async function fetchRealLocationData() {
726
- if ("geolocation" in navigator) {
727
- navigator.geolocation.getCurrentPosition(async (position) => {
728
- const lat = position.coords.latitude;
729
- const lon = position.coords.longitude;
730
-
731
- try {
732
- const geoRes = await fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lon}`);
733
- const geoData = await geoRes.json();
734
- const city = geoData.address.city || geoData.address.town || geoData.address.village || geoData.address.county || "Unknown Region";
735
- currentLocationStr = `${city}, ${geoData.address.country_code.toUpperCase()}`;
736
- if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = currentLocationStr;
737
- } catch(e) {
738
- if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = "Location API Error";
739
- }
740
-
741
- try {
742
- const wxRes = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current_weather=true`);
743
- const wxData = await wxRes.json();
744
- const temp = wxData.current_weather.temperature;
745
- if(document.getElementById('vWx')) document.getElementById('vWx').innerText = `${temp}°C, Active`;
746
- } catch(e) {
747
- if(document.getElementById('vWx')) document.getElementById('vWx').innerText = "--";
748
- }
749
- }, (error) => {
750
- if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = "Location Denied";
751
- if(document.getElementById('vWx')) document.getElementById('vWx').innerText = "--";
752
- });
753
- } else {
754
- if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = "Not Supported";
755
- }
756
- const now = new Date();
757
- if(document.getElementById('vTime')) document.getElementById('vTime').innerText = now.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
758
- }
759
-
760
  let streamId = null;
761
  let poller = null;
762
 
@@ -770,6 +731,8 @@
770
  function closePredictModal() {
771
  document.getElementById('predictiveModal').classList.add('hidden');
772
  document.body.style.overflow = '';
 
 
773
  }
774
  function resetPredictModal() {
775
  document.getElementById('predictiveResultView').classList.add('hidden');
@@ -780,7 +743,7 @@
780
  const url = document.getElementById('ipCamUrl').value;
781
  if(!url) return;
782
  closeIpCamModal();
783
- startSession({url: url, location: currentLocationStr}, '/init_stream');
784
  }
785
 
786
  document.getElementById('fileInput').addEventListener('change', async (e) => {
@@ -804,58 +767,48 @@
804
  const data = await res.json();
805
  streamId = data.stream_id;
806
 
807
- if(data.location && data.location !== "Nil" && document.getElementById('vLoc')) {
808
- document.getElementById('vLoc').innerText = data.location;
809
- } else {
810
- fetchRealLocationData(); // fallback
811
- }
812
 
813
- if(data.weather && data.weather !== "Nil" && document.getElementById('vWx')) {
814
- document.getElementById('vWx').innerText = data.weather;
815
- }
816
-
817
- activateTrackingUI();
818
 
819
- const locText = document.getElementById('vLoc') ? document.getElementById('vLoc').innerText : "Unknown";
820
- document.getElementById('previewImg').src = `/video_feed/${streamId}?loc=${encodeURIComponent(locText)}&t=${Date.now()}`;
821
- document.getElementById('rawFeedImg').src = `/raw_feed/${streamId}?loc=${encodeURIComponent(locText)}&t=${Date.now()}`;
822
 
823
  if(poller) clearInterval(poller);
824
  poller = setInterval(update, 1000);
825
  }
826
 
827
- function activateTrackingUI() {
828
- document.getElementById('previewImg').classList.remove('hidden');
829
- document.getElementById('rawFeedImg').classList.add('hidden');
830
- document.getElementById('snapshotContainer').classList.add('hidden');
831
- document.getElementById('liveBadgeContainer').classList.remove('hidden');
832
-
833
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
834
- if(document.getElementById('tBtn')) document.getElementById('tBtn').classList.add('opacity-50');
835
- if(document.getElementById('oBtn')) document.getElementById('oBtn').classList.remove('opacity-50');
 
 
 
836
  }
837
-
838
- function goTracking() { activateTrackingUI(); }
839
 
840
- function goOriginal() {
841
- document.getElementById('previewImg').classList.add('hidden');
842
- document.getElementById('rawFeedImg').classList.remove('hidden');
843
- document.getElementById('snapshotContainer').classList.add('hidden');
844
- document.getElementById('liveBadgeContainer').classList.remove('hidden');
845
-
846
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-blue-500 shadow-[0_0_8px_blue]"></span> RAW FEED';
847
- if(document.getElementById('oBtn')) document.getElementById('oBtn').classList.add('opacity-50');
848
- if(document.getElementById('tBtn')) document.getElementById('tBtn').classList.remove('opacity-50');
 
 
 
849
  }
850
 
851
  function takeSnapshot() {
852
- let feed = null;
853
- if(!document.getElementById('previewImg').classList.contains('hidden')) {
854
- feed = document.getElementById('previewImg');
855
- } else if (!document.getElementById('rawFeedImg').classList.contains('hidden')) {
856
- feed = document.getElementById('rawFeedImg');
857
- }
858
-
859
  if(feed && feed.src) {
860
  const c = document.createElement('canvas');
861
  c.width = feed.naturalWidth || feed.width || 640;
@@ -863,20 +816,16 @@
863
  c.getContext('2d').drawImage(feed, 0, 0, c.width, c.height);
864
 
865
  document.getElementById('snapshotImg').src = c.toDataURL('image/jpeg');
866
-
867
  document.getElementById('snapshotContainer').classList.remove('hidden');
868
  document.getElementById('previewImg').classList.add('hidden');
869
- document.getElementById('rawFeedImg').classList.add('hidden');
870
  document.getElementById('liveBadgeContainer').classList.add('hidden');
871
  }
872
  }
873
 
874
  function closeSnapshot() {
875
- if (document.getElementById('tBtn').classList.contains('opacity-50')) {
876
- goTracking();
877
- } else {
878
- goOriginal();
879
- }
880
  }
881
 
882
  function fullscreenSnapshot() {
@@ -906,17 +855,15 @@
906
  const statusIcon = document.getElementById('statusIcon');
907
  const emergencyBanner = document.getElementById('emergencyBanner');
908
 
909
- if(data.is_accident) {
910
- statusCard.classList.remove('border-indigo-500');
911
- statusCard.classList.add('border-rose-500', 'bg-rose-50/50', 'dark:bg-rose-900/20');
912
  statusIcon.className = "fas fa-exclamation-triangle text-rose-600";
913
 
914
  if(data.severity && (data.severity.toLowerCase() === 'major' || data.severity.toLowerCase() === 'moderate')) {
915
  emergencyBanner.classList.remove('hidden');
916
  }
917
  } else {
918
- statusCard.classList.add('border-indigo-500');
919
- statusCard.classList.remove('border-rose-500', 'bg-rose-50/50', 'dark:bg-rose-900/20');
920
  statusIcon.className = "fas fa-shield-check text-indigo-600";
921
  emergencyBanner.classList.add('hidden');
922
  }
@@ -935,15 +882,31 @@
935
  } catch(e) {}
936
  }
937
 
 
938
  function resetApp() {
939
  if(poller) clearInterval(poller);
940
  streamId = null;
941
  document.getElementById('previewImg').src = "";
942
- document.getElementById('rawFeedImg').src = "";
943
  document.getElementById('uploadSection').classList.remove('hidden');
944
  document.getElementById('results').classList.add('hidden');
945
  document.getElementById('emergencyBanner').classList.add('hidden');
 
 
 
946
  document.getElementById('fileInput').value = "";
 
 
 
 
 
 
 
 
 
 
 
 
 
947
  }
948
 
949
  async function submitPredictiveData(e) {
@@ -965,7 +928,8 @@
965
  Vehicle_Type: document.getElementById('tab_vehicle').value,
966
  Driver_Age: document.getElementById('tab_age').value,
967
  Driver_Experience: document.getElementById('tab_exp').value,
968
- Driver_Alcohol: document.getElementById('tab_alcohol').value
 
969
  };
970
 
971
  try {
@@ -979,32 +943,34 @@
979
  document.getElementById('predictiveFormView').classList.add('hidden');
980
  document.getElementById('predictiveResultView').classList.remove('hidden');
981
 
982
- const prob = data.risk_probability_percentage || 0;
983
- document.getElementById('riskProbabilityValue').innerText = prob;
984
-
985
  const riskCard = document.getElementById('riskStatusCard');
986
  const riskBadge = document.getElementById('riskBadge');
987
  const riskIcon = document.getElementById('riskIcon');
988
  const riskLabel = document.getElementById('riskLabelText');
 
989
 
990
  riskCard.className = 'ios-glass-inner p-10 rounded-[32px] shadow-sm dark:shadow-lg relative overflow-hidden w-full max-w-sm border';
991
  riskBadge.className = 'inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm text-white';
992
 
993
- if(prob >= 70) {
 
994
  riskCard.classList.add('border-red-500', 'bg-red-50/10', 'dark:bg-red-900/20');
995
  riskBadge.classList.add('bg-red-500', 'border-red-400');
996
  riskIcon.className = 'fas fa-exclamation-triangle';
997
- riskLabel.innerText = 'Critical Risk';
998
- } else if(prob >= 40) {
 
999
  riskCard.classList.add('border-amber-500', 'bg-amber-50/10', 'dark:bg-amber-900/20');
1000
  riskBadge.classList.add('bg-amber-500', 'border-amber-400');
1001
  riskIcon.className = 'fas fa-exclamation-circle';
1002
- riskLabel.innerText = 'Elevated Risk';
 
1003
  } else {
1004
  riskCard.classList.add('border-green-500', 'bg-green-50/10', 'dark:bg-green-900/20');
1005
  riskBadge.classList.add('bg-green-500', 'border-green-400');
1006
  riskIcon.className = 'fas fa-shield-check';
1007
- riskLabel.innerText = 'Low Risk';
 
1008
  }
1009
 
1010
  } catch (e) {
@@ -1014,9 +980,6 @@
1014
  spinner.classList.add('hidden');
1015
  }
1016
  }
1017
-
1018
- // Setup script initialization call
1019
- fetchRealLocationData();
1020
  </script>
1021
  </body>
1022
  </html>
 
156
  <h1 class="text-4xl font-black tracking-tight text-indigo-950 dark:text-white drop-shadow-sm">CrashVision AI</h1>
157
  <p class="text-xs font-black uppercase tracking-[0.3em] text-indigo-500 mt-3">Initializing Systems</p>
158
 
 
159
  <div class="mt-8 flex gap-3">
160
  <div class="w-3 h-3 rounded-md bg-fuchsia-500 animate-jiggle" style="animation-delay: 0s;"></div>
161
  <div class="w-3 h-3 rounded-md bg-indigo-500 animate-jiggle" style="animation-delay: 0.15s;"></div>
 
316
 
317
  <!-- Interactive Media Player Area -->
318
  <div class="rounded-[32px] overflow-hidden shadow-2xl border border-white/50 dark:border-white/20 relative bg-black aspect-video flex items-center justify-center group">
319
+ <!-- Display Image (Single video feed element) -->
320
+ <img id="previewImg" src="" class="w-full h-full object-contain z-10 hidden" alt="Video View">
 
 
321
 
322
  <!-- Snapshot Container Overlay -->
323
  <div id="snapshotContainer" class="absolute inset-0 z-30 hidden bg-black flex items-center justify-center">
 
364
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
365
  <i class="fas fa-location-dot text-rose-500 text-lg sm:text-xl mb-1 sm:mb-2"></i>
366
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Location</p>
367
+ <p id="vLoc" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center px-1 break-words">--</p>
368
  </div>
369
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
370
  <i class="fas fa-cloud-bolt text-cyan-500 text-lg sm:text-xl mb-1 sm:mb-2"></i>
371
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Conditions</p>
372
+ <p id="vWx" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center break-words">--</p>
373
  </div>
374
  <div class="ios-glass-inner p-3 sm:p-5 rounded-2xl sm:rounded-3xl flex flex-col items-center text-center gap-1 hover:bg-white/60 dark:hover:bg-white/10 transition-colors">
375
  <i class="fas fa-stopwatch text-indigo-500 dark:text-purple-300 text-lg sm:text-xl mb-1 sm:mb-2"></i>
376
  <p class="text-[8px] sm:text-[9px] uppercase tracking-widest text-indigo-800/50 dark:text-purple-200 font-black">Timeline</p>
377
+ <p id="vTime" class="text-[10px] sm:text-xs font-black text-indigo-950 dark:text-white w-full tracking-tight leading-tight text-center break-words">--</p>
378
  </div>
379
  </div>
380
  </div>
 
581
  </div>
582
  <div>
583
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Speed Limit</label>
584
+ <input type="number" id="tab_speed" placeholder="e.g. 60" min="10" max="250" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 shadow-sm">
585
  </div>
586
  </div>
587
  </div>
 
597
  <div class="space-y-4">
598
  <div>
599
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Density (0-5)</label>
600
+ <input type="number" id="tab_density" placeholder="e.g. 2" min="0" max="5" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
601
  </div>
602
  <div>
603
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicles Inv.</label>
604
+ <input type="number" id="tab_vehicles" placeholder="e.g. 2" min="1" max="20" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-amber-500 focus:ring-2 focus:ring-amber-500/20 shadow-sm">
605
  </div>
606
  <div>
607
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Vehicle Type</label>
 
626
  <div class="space-y-4">
627
  <div>
628
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Driver Age</label>
629
+ <input type="number" id="tab_age" placeholder="e.g. 35" min="16" max="99" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
630
  </div>
631
  <div>
632
  <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Experience (Yrs)</label>
633
+ <input type="number" id="tab_exp" placeholder="e.g. 5" min="0" max="80" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm">
634
  </div>
635
  <div>
636
+ <label class="block text-[10px] font-black uppercase tracking-widest text-indigo-900/70 dark:text-purple-200/70 mb-1.5 ml-1">Drunk</label>
637
+ <select id="tab_alcohol" class="predict-input bg-white/60 dark:bg-black/20 focus:bg-white dark:focus:bg-black/40 border border-indigo-200/60 dark:border-white/10 text-indigo-950 dark:text-white focus:border-fuchsia-500 focus:ring-2 focus:ring-fuchsia-500/20 shadow-sm cursor-pointer">
638
+ <option value="No">No</option>
639
+ <option value="Yes">Yes</option>
640
+ </select>
641
  </div>
642
  </div>
643
  </div>
 
665
  <span id="riskLabelText">Low Risk</span>
666
  </div>
667
 
668
+ <h4 class="text-6xl font-black tracking-tighter text-indigo-950 dark:text-white mb-2 drop-shadow-sm" id="riskLevelResult">--</h4>
669
+ <p class="text-indigo-800/60 dark:text-purple-200 text-[10px] font-black uppercase tracking-widest mt-4">Predicted Accident Severity</p>
670
  </div>
671
 
672
  <div class="flex gap-4 max-w-sm w-full mt-4">
 
689
  const themeToggleBtn = document.getElementById('themeToggle');
690
  const htmlElement = document.documentElement;
691
 
 
692
  if (localStorage.theme === 'dark') {
693
  htmlElement.classList.add('dark');
694
  } else {
 
705
  }
706
  });
707
 
 
708
  window.addEventListener('load', () => {
709
  setTimeout(() => {
710
  const splash = document.getElementById('appSplashScreen');
 
718
  }, 1800);
719
  });
720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  let streamId = null;
722
  let poller = null;
723
 
 
731
  function closePredictModal() {
732
  document.getElementById('predictiveModal').classList.add('hidden');
733
  document.body.style.overflow = '';
734
+ document.getElementById('tabularForm').reset(); // Wipe Predictor Form Data
735
+ resetPredictModal(); // Push back to form view
736
  }
737
  function resetPredictModal() {
738
  document.getElementById('predictiveResultView').classList.add('hidden');
 
743
  const url = document.getElementById('ipCamUrl').value;
744
  if(!url) return;
745
  closeIpCamModal();
746
+ startSession({url: url}, '/init_stream');
747
  }
748
 
749
  document.getElementById('fileInput').addEventListener('change', async (e) => {
 
767
  const data = await res.json();
768
  streamId = data.stream_id;
769
 
770
+ // Set metadata without browser fallback
771
+ if(document.getElementById('vLoc')) document.getElementById('vLoc').innerText = data.location || "--";
772
+ if(document.getElementById('vWx')) document.getElementById('vWx').innerText = data.weather || "--";
773
+ if(document.getElementById('vTime')) document.getElementById('vTime').innerText = data.time || "--";
 
774
 
775
+ // Instantly start UI logic
776
+ document.getElementById('previewImg').classList.remove('hidden');
777
+ document.getElementById('tBtn').classList.add('opacity-50');
778
+ document.getElementById('oBtn').classList.remove('opacity-50');
779
+ document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
780
 
781
+ document.getElementById('previewImg').src = `/video_feed/${streamId}?loc=${encodeURIComponent(data.location)}&t=${Date.now()}`;
 
 
782
 
783
  if(poller) clearInterval(poller);
784
  poller = setInterval(update, 1000);
785
  }
786
 
787
+ // Toggles AI boxes dynamically on backend via API request
788
+ async function goTracking() {
789
+ document.getElementById('tBtn').classList.add('opacity-50');
790
+ document.getElementById('oBtn').classList.remove('opacity-50');
 
 
791
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 animate-pulse shadow-[0_0_8px_red]"></span> LIVE AI FEED';
792
+ await fetch(`/toggle_tracking/${streamId}`, {
793
+ method: 'POST',
794
+ headers: {'Content-Type': 'application/json'},
795
+ body: JSON.stringify({track: true})
796
+ });
797
  }
 
 
798
 
799
+ async function goOriginal() {
800
+ document.getElementById('oBtn').classList.add('opacity-50');
801
+ document.getElementById('tBtn').classList.remove('opacity-50');
 
 
 
802
  document.getElementById('liveBadge').innerHTML = '<span class="w-2 h-2 rounded-full bg-blue-500 shadow-[0_0_8px_blue]"></span> RAW FEED';
803
+ await fetch(`/toggle_tracking/${streamId}`, {
804
+ method: 'POST',
805
+ headers: {'Content-Type': 'application/json'},
806
+ body: JSON.stringify({track: false})
807
+ });
808
  }
809
 
810
  function takeSnapshot() {
811
+ const feed = document.getElementById('previewImg');
 
 
 
 
 
 
812
  if(feed && feed.src) {
813
  const c = document.createElement('canvas');
814
  c.width = feed.naturalWidth || feed.width || 640;
 
816
  c.getContext('2d').drawImage(feed, 0, 0, c.width, c.height);
817
 
818
  document.getElementById('snapshotImg').src = c.toDataURL('image/jpeg');
 
819
  document.getElementById('snapshotContainer').classList.remove('hidden');
820
  document.getElementById('previewImg').classList.add('hidden');
 
821
  document.getElementById('liveBadgeContainer').classList.add('hidden');
822
  }
823
  }
824
 
825
  function closeSnapshot() {
826
+ document.getElementById('snapshotContainer').classList.add('hidden');
827
+ document.getElementById('previewImg').classList.remove('hidden');
828
+ document.getElementById('liveBadgeContainer').classList.remove('hidden');
 
 
829
  }
830
 
831
  function fullscreenSnapshot() {
 
855
  const statusIcon = document.getElementById('statusIcon');
856
  const emergencyBanner = document.getElementById('emergencyBanner');
857
 
858
+ if(data.is_accident || data.final_decision) {
859
+ statusCard.className = "ios-glass-inner p-8 rounded-[32px] mb-8 shadow-sm dark:shadow-lg relative overflow-hidden border-l-4 border-rose-500 bg-rose-50/50 dark:bg-rose-900/20 transition-colors duration-500";
 
860
  statusIcon.className = "fas fa-exclamation-triangle text-rose-600";
861
 
862
  if(data.severity && (data.severity.toLowerCase() === 'major' || data.severity.toLowerCase() === 'moderate')) {
863
  emergencyBanner.classList.remove('hidden');
864
  }
865
  } else {
866
+ statusCard.className = "ios-glass-inner p-8 rounded-[32px] mb-8 shadow-sm dark:shadow-lg relative overflow-hidden border-l-4 border-indigo-500 transition-colors duration-500";
 
867
  statusIcon.className = "fas fa-shield-check text-indigo-600";
868
  emergencyBanner.classList.add('hidden');
869
  }
 
882
  } catch(e) {}
883
  }
884
 
885
+ // Entire UI is reset completely when leaving
886
  function resetApp() {
887
  if(poller) clearInterval(poller);
888
  streamId = null;
889
  document.getElementById('previewImg').src = "";
 
890
  document.getElementById('uploadSection').classList.remove('hidden');
891
  document.getElementById('results').classList.add('hidden');
892
  document.getElementById('emergencyBanner').classList.add('hidden');
893
+ document.getElementById('alprSection').classList.add('hidden');
894
+
895
+ // Wipe Form and Upload fields completely
896
  document.getElementById('fileInput').value = "";
897
+ document.getElementById('uploadForm').reset();
898
+ document.getElementById('ipCamUrl').value = "";
899
+
900
+ // Reset Diagnostics View Default State
901
+ document.getElementById('confVal').innerText = "0";
902
+ document.getElementById('severityLevel').innerText = "--";
903
+ document.getElementById('cnnBar').style.width = "0%";
904
+ document.getElementById('rcnnBar').style.width = "0%";
905
+ document.getElementById('cnnVal').innerText = "0%";
906
+ document.getElementById('rcnnVal').innerText = "0%";
907
+ document.getElementById('labelText').innerText = "Scanning Stream...";
908
+ document.getElementById('statusCard').className = "ios-glass-inner p-8 rounded-[32px] mb-8 shadow-sm dark:shadow-lg relative overflow-hidden border-l-4 border-indigo-500 transition-colors duration-500";
909
+ document.getElementById('statusIcon').className = "fas fa-spinner fa-spin text-indigo-600";
910
  }
911
 
912
  async function submitPredictiveData(e) {
 
928
  Vehicle_Type: document.getElementById('tab_vehicle').value,
929
  Driver_Age: document.getElementById('tab_age').value,
930
  Driver_Experience: document.getElementById('tab_exp').value,
931
+ // Yes=1.0, No=0.0 mapped strictly here for the AI
932
+ Driver_Alcohol: document.getElementById('tab_alcohol').value === "Yes" ? 1.0 : 0.0
933
  };
934
 
935
  try {
 
943
  document.getElementById('predictiveFormView').classList.add('hidden');
944
  document.getElementById('predictiveResultView').classList.remove('hidden');
945
 
 
 
 
946
  const riskCard = document.getElementById('riskStatusCard');
947
  const riskBadge = document.getElementById('riskBadge');
948
  const riskIcon = document.getElementById('riskIcon');
949
  const riskLabel = document.getElementById('riskLabelText');
950
+ const riskText = document.getElementById('riskLevelResult');
951
 
952
  riskCard.className = 'ios-glass-inner p-10 rounded-[32px] shadow-sm dark:shadow-lg relative overflow-hidden w-full max-w-sm border';
953
  riskBadge.className = 'inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-black mb-6 uppercase tracking-[0.2em] border shadow-sm text-white';
954
 
955
+ // Displaying labels directly instead of percentages
956
+ if(data.status === "Major") {
957
  riskCard.classList.add('border-red-500', 'bg-red-50/10', 'dark:bg-red-900/20');
958
  riskBadge.classList.add('bg-red-500', 'border-red-400');
959
  riskIcon.className = 'fas fa-exclamation-triangle';
960
+ riskLabel.innerText = 'High Alert';
961
+ riskText.innerText = 'Major';
962
+ } else if(data.status === "Moderate") {
963
  riskCard.classList.add('border-amber-500', 'bg-amber-50/10', 'dark:bg-amber-900/20');
964
  riskBadge.classList.add('bg-amber-500', 'border-amber-400');
965
  riskIcon.className = 'fas fa-exclamation-circle';
966
+ riskLabel.innerText = 'Elevated Alert';
967
+ riskText.innerText = 'Moderate';
968
  } else {
969
  riskCard.classList.add('border-green-500', 'bg-green-50/10', 'dark:bg-green-900/20');
970
  riskBadge.classList.add('bg-green-500', 'border-green-400');
971
  riskIcon.className = 'fas fa-shield-check';
972
+ riskLabel.innerText = 'Safe Zone';
973
+ riskText.innerText = 'Minor';
974
  }
975
 
976
  } catch (e) {
 
980
  spinner.classList.add('hidden');
981
  }
982
  }
 
 
 
983
  </script>
984
  </body>
985
  </html>