{"ast":null,"code":"import React,{useState,useEffect}from'react';import{FiSearch,FiFilter,FiRefreshCw,FiDownload,FiCalendar,FiServer}from'react-icons/fi';import{Link}from'react-router-dom';// Dummy data for demonstration\nimport{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";const dummyLogs=[{id:1,device_id:'device-001',device_name:'SIM7000E-001',level:'info',message:'Device connected to network',source:'connection_manager',timestamp:new Date().toISOString()},{id:2,device_id:'device-001',device_name:'SIM7000E-001',level:'warning',message:'Battery level below 30%',source:'power_monitor',timestamp:new Date(Date.now()-1800000).toISOString()// 30 minutes ago\n},{id:3,device_id:'device-002',device_name:'SIM7000E-002',level:'error',message:'Failed to send telemetry data',source:'data_transmitter',timestamp:new Date(Date.now()-3600000).toISOString()// 1 hour ago\n},{id:4,device_id:'device-003',device_name:'SIM7000E-003',level:'critical',message:'Device shutdown due to critical battery level',source:'power_manager',timestamp:new Date(Date.now()-86400000).toISOString()// 1 day ago\n},{id:5,device_id:'device-004',device_name:'SIM7000E-004',level:'info',message:'GPS location updated',source:'gps_module',timestamp:new Date(Date.now()-7200000).toISOString()// 2 hours ago\n},{id:6,device_id:'device-001',device_name:'SIM7000E-001',level:'debug',message:'Reconnecting to cellular network',source:'connection_manager',timestamp:new Date(Date.now()-900000).toISOString()// 15 minutes ago\n},{id:7,device_id:'device-005',device_name:'SIM7000E-005',level:'warning',message:'Weak signal strength detected',source:'signal_monitor',timestamp:new Date(Date.now()-10800000).toISOString()// 3 hours ago\n},{id:8,device_id:'device-002',device_name:'SIM7000E-002',level:'info',message:'Firmware update available',source:'update_manager',timestamp:new Date(Date.now()-43200000).toISOString()// 12 hours ago\n},{id:9,device_id:'device-004',device_name:'SIM7000E-004',level:'error',message:'Temperature sensor reading out of range',source:'sensor_monitor',timestamp:new Date(Date.now()-14400000).toISOString()// 4 hours ago\n},{id:10,device_id:'device-003',device_name:'SIM7000E-003',level:'debug',message:'Device configuration updated',source:'config_manager',timestamp:new Date(Date.now()-172800000).toISOString()// 2 days ago\n}];const Logs=()=>{const[logs,setLogs]=useState([]);const[loading,setLoading]=useState(true);const[searchTerm,setSearchTerm]=useState('');const[levelFilter,setLevelFilter]=useState('all');const[deviceFilter,setDeviceFilter]=useState('all');const[refreshing,setRefreshing]=useState(false);const[startDate,setStartDate]=useState('');const[endDate,setEndDate]=useState('');useEffect(()=>{// Simulate API call\nconst fetchData=async()=>{try{// In a real app, you would fetch data from your API\n// const response = await fetch('/api/logs');\n// const data = await response.json();\n// Using dummy data for now\nsetTimeout(()=>{setLogs(dummyLogs);setLoading(false);},1000);}catch(error){console.error('Error fetching data:',error);setLoading(false);}};fetchData();},[]);// Helper function to format date\nconst formatDate=dateString=>{const date=new Date(dateString);return date.toLocaleString();};// Helper function to get log level color\nconst getLevelColor=level=>{switch(level){case'debug':return'text-gray-500 bg-gray-100';case'info':return'text-blue-500 bg-blue-100';case'warning':return'text-yellow-500 bg-yellow-100';case'error':return'text-red-500 bg-red-100';case'critical':return'text-white bg-red-500';default:return'text-gray-500 bg-gray-100';}};// Handle refresh\nconst handleRefresh=()=>{setRefreshing(true);// Simulate API call\nsetTimeout(()=>{setLogs(dummyLogs);setRefreshing(false);},1000);};// Handle export logs\nconst handleExportLogs=()=>{// In a real app, you would generate a CSV or JSON file\nalert('Exporting logs functionality would be implemented here');};// Get unique device IDs for filter dropdown\nconst uniqueDevices=[...new Set(logs.map(log=>log.device_id))];// Filter logs based on search term, level filter, device filter, and date range\nconst filteredLogs=logs.filter(log=>{const matchesSearch=log.message.toLowerCase().includes(searchTerm.toLowerCase())||log.source.toLowerCase().includes(searchTerm.toLowerCase())||log.device_id.toLowerCase().includes(searchTerm.toLowerCase());const matchesLevel=levelFilter==='all'||log.level===levelFilter;const matchesDevice=deviceFilter==='all'||log.device_id===deviceFilter;let matchesDateRange=true;if(startDate){const logDate=new Date(log.timestamp);const filterStartDate=new Date(startDate);matchesDateRange=logDate>=filterStartDate;}if(endDate){const logDate=new Date(log.timestamp);const filterEndDate=new Date(endDate);// Set end date to end of day\nfilterEndDate.setHours(23,59,59,999);matchesDateRange=matchesDateRange&&logDate<=filterEndDate;}return matchesSearch&&matchesLevel&&matchesDevice&&matchesDateRange;});if(loading){return/*#__PURE__*/_jsx(\"div\",{className:\"flex items-center justify-center h-full\",children:/*#__PURE__*/_jsxs(\"div\",{className:\"text-center\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"w-16 h-16 border-4 border-primary-500 border-t-transparent rounded-full animate-spin mx-auto\"}),/*#__PURE__*/_jsx(\"p\",{className:\"mt-4 text-gray-600\",children:\"Loading logs...\"})]})});}return/*#__PURE__*/_jsxs(\"div\",{className:\"space-y-6\",children:[/*#__PURE__*/_jsxs(\"div\",{className:\"flex justify-between items-center\",children:[/*#__PURE__*/_jsx(\"h1\",{className:\"text-2xl font-semibold text-gray-800\",children:\"System Logs\"}),/*#__PURE__*/_jsxs(\"button\",{className:\"flex items-center gap-2 px-4 py-2 bg-primary-500 text-white rounded-md hover:bg-primary-600 transition-colors\",onClick:handleExportLogs,children:[/*#__PURE__*/_jsx(FiDownload,{}),/*#__PURE__*/_jsx(\"span\",{children:\"Export Logs\"})]})]}),/*#__PURE__*/_jsxs(\"div\",{className:\"dashboard-card\",children:[/*#__PURE__*/_jsxs(\"div\",{className:\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4\",children:[/*#__PURE__*/_jsxs(\"div\",{className:\"relative\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\",children:/*#__PURE__*/_jsx(FiSearch,{className:\"text-gray-400\"})}),/*#__PURE__*/_jsx(\"input\",{type:\"text\",placeholder:\"Search logs...\",className:\"block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm\",value:searchTerm,onChange:e=>setSearchTerm(e.target.value)})]}),/*#__PURE__*/_jsxs(\"div\",{className:\"relative\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\",children:/*#__PURE__*/_jsx(FiFilter,{className:\"text-gray-400\"})}),/*#__PURE__*/_jsxs(\"select\",{className:\"block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm\",value:levelFilter,onChange:e=>setLevelFilter(e.target.value),children:[/*#__PURE__*/_jsx(\"option\",{value:\"all\",children:\"All Levels\"}),/*#__PURE__*/_jsx(\"option\",{value:\"debug\",children:\"Debug\"}),/*#__PURE__*/_jsx(\"option\",{value:\"info\",children:\"Info\"}),/*#__PURE__*/_jsx(\"option\",{value:\"warning\",children:\"Warning\"}),/*#__PURE__*/_jsx(\"option\",{value:\"error\",children:\"Error\"}),/*#__PURE__*/_jsx(\"option\",{value:\"critical\",children:\"Critical\"})]})]}),/*#__PURE__*/_jsxs(\"div\",{className:\"relative\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\",children:/*#__PURE__*/_jsx(FiServer,{className:\"text-gray-400\"})}),/*#__PURE__*/_jsxs(\"select\",{className:\"block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm\",value:deviceFilter,onChange:e=>setDeviceFilter(e.target.value),children:[/*#__PURE__*/_jsx(\"option\",{value:\"all\",children:\"All Devices\"}),uniqueDevices.map(deviceId=>{var _logs$find;return/*#__PURE__*/_jsx(\"option\",{value:deviceId,children:((_logs$find=logs.find(log=>log.device_id===deviceId))===null||_logs$find===void 0?void 0:_logs$find.device_name)||deviceId},deviceId);})]})]}),/*#__PURE__*/_jsxs(\"button\",{className:`flex items-center justify-center gap-2 px-4 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors ${refreshing?'opacity-50 cursor-not-allowed':''}`,onClick:handleRefresh,disabled:refreshing,children:[/*#__PURE__*/_jsx(FiRefreshCw,{className:refreshing?'animate-spin':''}),/*#__PURE__*/_jsx(\"span\",{children:\"Refresh\"})]})]}),/*#__PURE__*/_jsxs(\"div\",{className:\"grid grid-cols-1 md:grid-cols-2 gap-4\",children:[/*#__PURE__*/_jsxs(\"div\",{className:\"relative\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\",children:/*#__PURE__*/_jsx(FiCalendar,{className:\"text-gray-400\"})}),/*#__PURE__*/_jsx(\"input\",{type:\"date\",placeholder:\"Start Date\",className:\"block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm\",value:startDate,onChange:e=>setStartDate(e.target.value)})]}),/*#__PURE__*/_jsxs(\"div\",{className:\"relative\",children:[/*#__PURE__*/_jsx(\"div\",{className:\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\",children:/*#__PURE__*/_jsx(FiCalendar,{className:\"text-gray-400\"})}),/*#__PURE__*/_jsx(\"input\",{type:\"date\",placeholder:\"End Date\",className:\"block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm\",value:endDate,onChange:e=>setEndDate(e.target.value)})]})]})]}),/*#__PURE__*/_jsx(\"div\",{className:\"dashboard-card\",children:filteredLogs.length===0?/*#__PURE__*/_jsx(\"div\",{className:\"text-center py-8\",children:/*#__PURE__*/_jsx(\"p\",{className:\"text-gray-500\",children:\"No logs found matching your criteria.\"})}):/*#__PURE__*/_jsx(\"div\",{className:\"overflow-x-auto\",children:/*#__PURE__*/_jsxs(\"table\",{className:\"min-w-full divide-y divide-gray-200\",children:[/*#__PURE__*/_jsx(\"thead\",{className:\"bg-gray-50\",children:/*#__PURE__*/_jsxs(\"tr\",{children:[/*#__PURE__*/_jsx(\"th\",{className:\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\",children:\"Timestamp\"}),/*#__PURE__*/_jsx(\"th\",{className:\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\",children:\"Level\"}),/*#__PURE__*/_jsx(\"th\",{className:\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\",children:\"Device\"}),/*#__PURE__*/_jsx(\"th\",{className:\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\",children:\"Message\"}),/*#__PURE__*/_jsx(\"th\",{className:\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\",children:\"Source\"})]})}),/*#__PURE__*/_jsx(\"tbody\",{className:\"bg-white divide-y divide-gray-200\",children:filteredLogs.map(log=>/*#__PURE__*/_jsxs(\"tr\",{className:\"hover:bg-gray-50\",children:[/*#__PURE__*/_jsx(\"td\",{className:\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\",children:formatDate(log.timestamp)}),/*#__PURE__*/_jsx(\"td\",{className:\"px-6 py-4 whitespace-nowrap\",children:/*#__PURE__*/_jsx(\"span\",{className:`px-2 py-1 text-xs font-medium rounded-full ${getLevelColor(log.level)}`,children:log.level.toUpperCase()})}),/*#__PURE__*/_jsx(\"td\",{className:\"px-6 py-4 whitespace-nowrap\",children:/*#__PURE__*/_jsx(Link,{to:`/devices/${log.device_id}`,className:\"text-primary-600 hover:text-primary-700\",children:log.device_name})}),/*#__PURE__*/_jsx(\"td\",{className:\"px-6 py-4 text-sm text-gray-900\",children:log.message}),/*#__PURE__*/_jsx(\"td\",{className:\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\",children:log.source})]},log.id))})]})})})]});};export default Logs;","map":{"version":3,"names":["React","useState","useEffect","FiSearch","FiFilter","FiRefreshCw","FiDownload","FiCalendar","FiServer","Link","jsx","_jsx","jsxs","_jsxs","dummyLogs","id","device_id","device_name","level","message","source","timestamp","Date","toISOString","now","Logs","logs","setLogs","loading","setLoading","searchTerm","setSearchTerm","levelFilter","setLevelFilter","deviceFilter","setDeviceFilter","refreshing","setRefreshing","startDate","setStartDate","endDate","setEndDate","fetchData","setTimeout","error","console","formatDate","dateString","date","toLocaleString","getLevelColor","handleRefresh","handleExportLogs","alert","uniqueDevices","Set","map","log","filteredLogs","filter","matchesSearch","toLowerCase","includes","matchesLevel","matchesDevice","matchesDateRange","logDate","filterStartDate","filterEndDate","setHours","className","children","onClick","type","placeholder","value","onChange","e","target","deviceId","_logs$find","find","disabled","length","toUpperCase","to"],"sources":["/home/m3mo/Desktop/temparea/solarbank/frontend/src/pages/Logs.js"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { FiSearch, FiFilter, FiRefreshCw, FiDownload, FiCalendar, FiServer } from 'react-icons/fi';\nimport { Link } from 'react-router-dom';\n\n// Dummy data for demonstration\nconst dummyLogs = [\n {\n id: 1,\n device_id: 'device-001',\n device_name: 'SIM7000E-001',\n level: 'info',\n message: 'Device connected to network',\n source: 'connection_manager',\n timestamp: new Date().toISOString()\n },\n {\n id: 2,\n device_id: 'device-001',\n device_name: 'SIM7000E-001',\n level: 'warning',\n message: 'Battery level below 30%',\n source: 'power_monitor',\n timestamp: new Date(Date.now() - 1800000).toISOString() // 30 minutes ago\n },\n {\n id: 3,\n device_id: 'device-002',\n device_name: 'SIM7000E-002',\n level: 'error',\n message: 'Failed to send telemetry data',\n source: 'data_transmitter',\n timestamp: new Date(Date.now() - 3600000).toISOString() // 1 hour ago\n },\n {\n id: 4,\n device_id: 'device-003',\n device_name: 'SIM7000E-003',\n level: 'critical',\n message: 'Device shutdown due to critical battery level',\n source: 'power_manager',\n timestamp: new Date(Date.now() - 86400000).toISOString() // 1 day ago\n },\n {\n id: 5,\n device_id: 'device-004',\n device_name: 'SIM7000E-004',\n level: 'info',\n message: 'GPS location updated',\n source: 'gps_module',\n timestamp: new Date(Date.now() - 7200000).toISOString() // 2 hours ago\n },\n {\n id: 6,\n device_id: 'device-001',\n device_name: 'SIM7000E-001',\n level: 'debug',\n message: 'Reconnecting to cellular network',\n source: 'connection_manager',\n timestamp: new Date(Date.now() - 900000).toISOString() // 15 minutes ago\n },\n {\n id: 7,\n device_id: 'device-005',\n device_name: 'SIM7000E-005',\n level: 'warning',\n message: 'Weak signal strength detected',\n source: 'signal_monitor',\n timestamp: new Date(Date.now() - 10800000).toISOString() // 3 hours ago\n },\n {\n id: 8,\n device_id: 'device-002',\n device_name: 'SIM7000E-002',\n level: 'info',\n message: 'Firmware update available',\n source: 'update_manager',\n timestamp: new Date(Date.now() - 43200000).toISOString() // 12 hours ago\n },\n {\n id: 9,\n device_id: 'device-004',\n device_name: 'SIM7000E-004',\n level: 'error',\n message: 'Temperature sensor reading out of range',\n source: 'sensor_monitor',\n timestamp: new Date(Date.now() - 14400000).toISOString() // 4 hours ago\n },\n {\n id: 10,\n device_id: 'device-003',\n device_name: 'SIM7000E-003',\n level: 'debug',\n message: 'Device configuration updated',\n source: 'config_manager',\n timestamp: new Date(Date.now() - 172800000).toISOString() // 2 days ago\n }\n];\n\nconst Logs = () => {\n const [logs, setLogs] = useState([]);\n const [loading, setLoading] = useState(true);\n const [searchTerm, setSearchTerm] = useState('');\n const [levelFilter, setLevelFilter] = useState('all');\n const [deviceFilter, setDeviceFilter] = useState('all');\n const [refreshing, setRefreshing] = useState(false);\n const [startDate, setStartDate] = useState('');\n const [endDate, setEndDate] = useState('');\n\n useEffect(() => {\n // Simulate API call\n const fetchData = async () => {\n try {\n // In a real app, you would fetch data from your API\n // const response = await fetch('/api/logs');\n // const data = await response.json();\n \n // Using dummy data for now\n setTimeout(() => {\n setLogs(dummyLogs);\n setLoading(false);\n }, 1000);\n } catch (error) {\n console.error('Error fetching data:', error);\n setLoading(false);\n }\n };\n\n fetchData();\n }, []);\n\n // Helper function to format date\n const formatDate = (dateString) => {\n const date = new Date(dateString);\n return date.toLocaleString();\n };\n\n // Helper function to get log level color\n const getLevelColor = (level) => {\n switch (level) {\n case 'debug':\n return 'text-gray-500 bg-gray-100';\n case 'info':\n return 'text-blue-500 bg-blue-100';\n case 'warning':\n return 'text-yellow-500 bg-yellow-100';\n case 'error':\n return 'text-red-500 bg-red-100';\n case 'critical':\n return 'text-white bg-red-500';\n default:\n return 'text-gray-500 bg-gray-100';\n }\n };\n\n // Handle refresh\n const handleRefresh = () => {\n setRefreshing(true);\n // Simulate API call\n setTimeout(() => {\n setLogs(dummyLogs);\n setRefreshing(false);\n }, 1000);\n };\n\n // Handle export logs\n const handleExportLogs = () => {\n // In a real app, you would generate a CSV or JSON file\n alert('Exporting logs functionality would be implemented here');\n };\n\n // Get unique device IDs for filter dropdown\n const uniqueDevices = [...new Set(logs.map(log => log.device_id))];\n\n // Filter logs based on search term, level filter, device filter, and date range\n const filteredLogs = logs.filter(log => {\n const matchesSearch = log.message.toLowerCase().includes(searchTerm.toLowerCase()) ||\n log.source.toLowerCase().includes(searchTerm.toLowerCase()) ||\n log.device_id.toLowerCase().includes(searchTerm.toLowerCase());\n \n const matchesLevel = levelFilter === 'all' || log.level === levelFilter;\n \n const matchesDevice = deviceFilter === 'all' || log.device_id === deviceFilter;\n \n let matchesDateRange = true;\n if (startDate) {\n const logDate = new Date(log.timestamp);\n const filterStartDate = new Date(startDate);\n matchesDateRange = logDate >= filterStartDate;\n }\n \n if (endDate) {\n const logDate = new Date(log.timestamp);\n const filterEndDate = new Date(endDate);\n // Set end date to end of day\n filterEndDate.setHours(23, 59, 59, 999);\n matchesDateRange = matchesDateRange && logDate <= filterEndDate;\n }\n \n return matchesSearch && matchesLevel && matchesDevice && matchesDateRange;\n });\n\n if (loading) {\n return (\n
Loading logs...
\nNo logs found matching your criteria.
\n| Timestamp | \nLevel | \nDevice | \nMessage | \nSource | \n
|---|---|---|---|---|
| \n {formatDate(log.timestamp)}\n | \n\n \n {log.level.toUpperCase()}\n \n | \n\n \n {log.device_name}\n \n | \n\n {log.message}\n | \n\n {log.source}\n | \n