'use client'; import { useState, useEffect } from 'react'; import Link from 'next/link'; import dynamic from 'next/dynamic'; import { format } from 'date-fns'; import { SensorWithLatestReading } from '@/lib/types'; import SensorDashboard from './SensorDashboard'; import { ChatBot } from './ChatBot'; // Dynamically import map to avoid SSR issues const MiniMap = dynamic(() => import('./MiniMap'), { ssr: false }); interface SensorDetailPageProps { sensor: SensorWithLatestReading; } export default function SensorDetailPage({ sensor: initialSensor }: SensorDetailPageProps) { const [sensor, setSensor] = useState(initialSensor); const [latestReading, setLatestReading] = useState(initialSensor.latestReading); const [refreshing, setRefreshing] = useState(false); const [refreshKey, setRefreshKey] = useState(0); const fetchLatestReading = async (sensorId: string) => { try { const url = new URL('/api/readings', window.location.origin); url.searchParams.append('sensorId', sensorId); url.searchParams.append('latest', 'true'); const response = await fetch(url.toString()); if (!response.ok) throw new Error('Failed to fetch latest reading'); const readings = await response.json(); console.log("here") console.log(readings[0]) if (readings.length > 0) { setLatestReading(readings[0]); } } catch (error) { console.error('Error fetching latest reading:', error); } }; const refreshData = async () => { setRefreshing(true); console.log('refreshing...'); try { const response = await fetch('/api/sensors'); const sensors = await response.json(); console.log(sensors) const updatedSensor = sensors.find((s: any) => s.sensorId === sensor.sensorId); if (updatedSensor) { setSensor({ ...updatedSensor }); setRefreshKey(prev => prev + 1); } // Fetch the latest reading from the readings API await fetchLatestReading(sensor.sensorId); } catch (error) { console.error('Error refreshing sensor data:', error); } finally { setRefreshing(false); } }; // Auto-refresh every 30 seconds useEffect(() => { const interval = setInterval(refreshData, 30000); return () => clearInterval(interval); }, [sensor.sensorId]); // Fetch latest reading on mount useEffect(() => { fetchLatestReading(sensor.sensorId); }, [sensor.sensorId]); return (
{/* HEADER */}

{sensor.locationName || sensor.sensorId}

Sensor • Installed {format(new Date(sensor.installedAt), 'MMM dd, yyyy')}

{/* CONTENT */}
{/* LEFT PANEL */}
{/* CURRENT METRICS */}

Current Water Quality

{latestReading ? (
) : (

No live readings

)}
{/* LOCATION */}

Sensor Location

{sensor.latitude.toFixed(5)} {sensor.longitude.toFixed(5)}
{/* RIGHT PANEL */}

Historical Analytics

{/* ChatBot Bubble */}
); } function PotabilityGauge({ potability }: { potability: number | null | undefined }) { if (potability === null || potability === undefined) { return (

Awaiting ML Model Inference

); } const potabilityPercent = potability * 100; const radius = 35; const strokeWidth = 6; const circumference = 2 * Math.PI * radius; const offset = circumference - potability * circumference; const hue = potability * 120; const dynamicColor = `hsl(${hue}, 80%, 45%)`; return (
{Math.round(potabilityPercent)} SCORE

ML Potability Index

Real-time confidence score generated by continuous neural network analysis. Color maps from hazardous to pure.

); } function ReadingCard({ label, value, unit, icon, color }: { label: string; value: string; unit: string; icon: string; color: string; }) { return (
{icon} {value} {unit && {unit}}

{label}

); }