Add AIOptimizationView for managing AI optimizations
This commit is contained in:
@@ -46,17 +46,25 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="flex flex-col items-center text-gray-600 hover:text-green-600" href="#">
|
<router-link
|
||||||
|
to="/ai-optimization"
|
||||||
|
class="flex flex-col items-center font-medium"
|
||||||
|
:class="
|
||||||
|
$route.name === 'ai-optimization'
|
||||||
|
? 'text-purple-600'
|
||||||
|
: 'text-gray-600 hover:text-purple-600'
|
||||||
|
"
|
||||||
|
>
|
||||||
<svg class="w-6 h-6 mb-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-6 h-6 mb-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path
|
<path
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
d="M13 10V3L4 14h7v7l9-11h-7z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="text-xs">Analytics</span>
|
<span class="text-xs">AI Optimize</span>
|
||||||
</a>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import HomeView from '../views/HomeView.vue'
|
import HomeView from '../views/HomeView.vue'
|
||||||
import SensorManagementView from '../views/SensorManagementView.vue'
|
import SensorManagementView from '../views/SensorManagementView.vue'
|
||||||
|
import AIOptimizationView from '../views/AIOptimizationView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -15,6 +16,11 @@ const router = createRouter({
|
|||||||
name: 'sensors',
|
name: 'sensors',
|
||||||
component: SensorManagementView,
|
component: SensorManagementView,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/ai-optimization',
|
||||||
|
name: 'ai-optimization',
|
||||||
|
component: AIOptimizationView,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
606
src/views/AIOptimizationView.vue
Normal file
606
src/views/AIOptimizationView.vue
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
<template>
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
||||||
|
<div>
|
||||||
|
<h1 class="text-2xl font-bold text-gray-900">AI Optimization</h1>
|
||||||
|
<p class="text-gray-600">Leverage artificial intelligence to optimize energy consumption and building operations</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 sm:mt-0">
|
||||||
|
<div class="flex items-center gap-2 text-sm text-gray-600">
|
||||||
|
<div
|
||||||
|
class="w-3 h-3 rounded-full"
|
||||||
|
:class="energyStore.isConnected ? 'bg-green-500' : 'bg-red-500'"
|
||||||
|
></div>
|
||||||
|
<span>{{ energyStore.isConnected ? 'Connected' : 'Disconnected' }}</span>
|
||||||
|
<span class="mx-2">•</span>
|
||||||
|
<span>{{ activeOptimizations.length }} active optimizations</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Stats -->
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-green-100 rounded-lg">
|
||||||
|
<span class="text-lg">💰</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">Estimated Savings</div>
|
||||||
|
<div class="text-lg font-semibold text-gray-900">$2,431/mo</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-blue-100 rounded-lg">
|
||||||
|
<span class="text-lg">⚡</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">Energy Reduced</div>
|
||||||
|
<div class="text-lg font-semibold text-gray-900">18.3%</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-purple-100 rounded-lg">
|
||||||
|
<span class="text-lg">🤖</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">AI Actions</div>
|
||||||
|
<div class="text-lg font-semibold text-gray-900">{{ totalAIActions }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-orange-100 rounded-lg">
|
||||||
|
<span class="text-lg">🌡️</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">Comfort Score</div>
|
||||||
|
<div class="text-lg font-semibold text-gray-900">8.7/10</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Optimization Categories -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
<!-- HVAC Optimization -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-cyan-100 rounded-lg">
|
||||||
|
<span class="text-lg">❄️</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold text-gray-900">HVAC Optimization</h3>
|
||||||
|
<p class="text-sm text-gray-600">Smart climate control and energy efficiency</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full font-medium">
|
||||||
|
Active
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Predictive Temperature Control</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('hvac', 'predictive_temp')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'predictive_temp') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'predictive_temp') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Occupancy-based Scheduling</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('hvac', 'occupancy_schedule')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'occupancy_schedule') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'occupancy_schedule') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Weather-based Adjustments</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('hvac', 'weather_adjust')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'weather_adjust') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('hvac', 'weather_adjust') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pt-3 border-t border-gray-100">
|
||||||
|
<div class="text-xs text-gray-500 mb-2">Performance</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-gray-600">Energy Savings:</span>
|
||||||
|
<span class="font-medium text-green-600">-23.1%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm mt-1">
|
||||||
|
<span class="text-gray-600">Comfort Score:</span>
|
||||||
|
<span class="font-medium text-blue-600">9.1/10</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Lighting Optimization -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-amber-100 rounded-lg">
|
||||||
|
<span class="text-lg">💡</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold text-gray-900">Lighting Optimization</h3>
|
||||||
|
<p class="text-sm text-gray-600">Adaptive lighting and energy management</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full font-medium">
|
||||||
|
Active
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Daylight Harvesting</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('lighting', 'daylight_harvest')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'daylight_harvest') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'daylight_harvest') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Motion-based Control</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('lighting', 'motion_control')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'motion_control') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'motion_control') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Circadian Rhythm Sync</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('lighting', 'circadian_sync')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'circadian_sync') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('lighting', 'circadian_sync') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pt-3 border-t border-gray-100">
|
||||||
|
<div class="text-xs text-gray-500 mb-2">Performance</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-gray-600">Energy Savings:</span>
|
||||||
|
<span class="font-medium text-green-600">-31.7%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm mt-1">
|
||||||
|
<span class="text-gray-600">User Satisfaction:</span>
|
||||||
|
<span class="font-medium text-blue-600">8.9/10</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Security & Access Optimization -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-purple-100 rounded-lg">
|
||||||
|
<span class="text-lg">🔒</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold text-gray-900">Security Optimization</h3>
|
||||||
|
<p class="text-sm text-gray-600">Intelligent access control and monitoring</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-xs px-2 py-1 bg-yellow-100 text-yellow-700 rounded-full font-medium">
|
||||||
|
Partial
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Adaptive Access Control</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('security', 'adaptive_access')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('security', 'adaptive_access') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('security', 'adaptive_access') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Anomaly Detection</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('security', 'anomaly_detection')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('security', 'anomaly_detection') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('security', 'anomaly_detection') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Predictive Maintenance</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('security', 'predictive_maintenance')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('security', 'predictive_maintenance') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('security', 'predictive_maintenance') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pt-3 border-t border-gray-100">
|
||||||
|
<div class="text-xs text-gray-500 mb-2">Performance</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-gray-600">Incidents Prevented:</span>
|
||||||
|
<span class="font-medium text-green-600">12 this month</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm mt-1">
|
||||||
|
<span class="text-gray-600">Response Time:</span>
|
||||||
|
<span class="font-medium text-blue-600">-45%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Air Quality Optimization -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-green-100 rounded-lg">
|
||||||
|
<span class="text-lg">💨</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold text-gray-900">Air Quality Optimization</h3>
|
||||||
|
<p class="text-sm text-gray-600">Intelligent ventilation and air management</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full font-medium">
|
||||||
|
Active
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">CO2-based Ventilation</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('air_quality', 'co2_ventilation')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'co2_ventilation') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'co2_ventilation') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Smart Air Filtration</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('air_quality', 'smart_filtration')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'smart_filtration') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'smart_filtration') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm text-gray-600">Humidity Control</span>
|
||||||
|
<button
|
||||||
|
@click="toggleOptimization('air_quality', 'humidity_control')"
|
||||||
|
class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'humidity_control') ? 'bg-blue-600' : 'bg-gray-200'"
|
||||||
|
>
|
||||||
|
<span class="inline-block h-3 w-3 transform rounded-full bg-white transition-transform"
|
||||||
|
:class="isOptimizationEnabled('air_quality', 'humidity_control') ? 'translate-x-5' : 'translate-x-1'"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pt-3 border-t border-gray-100">
|
||||||
|
<div class="text-xs text-gray-500 mb-2">Performance</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-gray-600">Air Quality Index:</span>
|
||||||
|
<span class="font-medium text-green-600">Excellent</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm mt-1">
|
||||||
|
<span class="text-gray-600">Energy Impact:</span>
|
||||||
|
<span class="font-medium text-blue-600">-8.2%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Active Optimizations & Schedule -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
<!-- Active Optimizations -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<h3 class="font-semibold text-gray-900">Active AI Optimizations</h3>
|
||||||
|
<p class="text-sm text-gray-600 mt-1">Currently running optimization tasks</p>
|
||||||
|
</div>
|
||||||
|
<div class="divide-y divide-gray-100">
|
||||||
|
<div v-for="optimization in activeOptimizations" :key="optimization.id" class="p-4">
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-1.5 rounded" :class="optimization.statusColor">
|
||||||
|
<span class="text-sm">{{ optimization.icon }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="font-medium text-gray-900">{{ optimization.name }}</div>
|
||||||
|
<div class="text-xs text-gray-500">{{ optimization.description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
@click="pauseOptimization(optimization.id)"
|
||||||
|
class="text-xs px-2 py-1 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded font-medium transition-colors"
|
||||||
|
>
|
||||||
|
Pause
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between text-xs text-gray-600">
|
||||||
|
<span>Started: {{ optimization.startTime }}</span>
|
||||||
|
<span class="font-medium" :class="optimization.impactColor">{{ optimization.impact }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-t border-gray-100">
|
||||||
|
<button
|
||||||
|
@click="showNewOptimizationModal = true"
|
||||||
|
class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition-colors"
|
||||||
|
>
|
||||||
|
Configure New Optimization
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Optimization Schedule -->
|
||||||
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
<div class="p-4 border-b border-gray-100">
|
||||||
|
<h3 class="font-semibold text-gray-900">Optimization Schedule</h3>
|
||||||
|
<p class="text-sm text-gray-600 mt-1">Upcoming automated optimizations</p>
|
||||||
|
</div>
|
||||||
|
<div class="divide-y divide-gray-100">
|
||||||
|
<div v-for="schedule in upcomingOptimizations" :key="schedule.id" class="p-4">
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-1.5 bg-gray-100 rounded">
|
||||||
|
<span class="text-sm">{{ schedule.icon }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="font-medium text-gray-900">{{ schedule.name }}</div>
|
||||||
|
<div class="text-xs text-gray-500">{{ schedule.rooms.join(', ') }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs px-2 py-1 bg-blue-100 text-blue-700 rounded font-medium">
|
||||||
|
{{ schedule.frequency }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs text-gray-600">
|
||||||
|
Next run: {{ schedule.nextRun }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-t border-gray-100">
|
||||||
|
<button
|
||||||
|
@click="showScheduleModal = true"
|
||||||
|
class="w-full px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg text-sm font-medium transition-colors"
|
||||||
|
>
|
||||||
|
Manage Schedule
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- New Optimization Modal Placeholder -->
|
||||||
|
<div v-if="showNewOptimizationModal" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
|
||||||
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 mb-4">New AI Optimization</h3>
|
||||||
|
<p class="text-gray-600 mb-4">Select an optimization type to configure:</p>
|
||||||
|
<div class="space-y-2 mb-6">
|
||||||
|
<button class="w-full p-3 text-left border border-gray-200 rounded-lg hover:border-blue-300 transition-colors">
|
||||||
|
<div class="font-medium text-gray-900">Custom HVAC Schedule</div>
|
||||||
|
<div class="text-sm text-gray-600">Create room-specific temperature schedules</div>
|
||||||
|
</button>
|
||||||
|
<button class="w-full p-3 text-left border border-gray-200 rounded-lg hover:border-blue-300 transition-colors">
|
||||||
|
<div class="font-medium text-gray-900">Energy Load Balancing</div>
|
||||||
|
<div class="text-sm text-gray-600">Distribute energy usage across peak times</div>
|
||||||
|
</button>
|
||||||
|
<button class="w-full p-3 text-left border border-gray-200 rounded-lg hover:border-blue-300 transition-colors">
|
||||||
|
<div class="font-medium text-gray-900">Predictive Maintenance</div>
|
||||||
|
<div class="text-sm text-gray-600">AI-driven equipment monitoring</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<button
|
||||||
|
@click="showNewOptimizationModal = false"
|
||||||
|
class="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg text-sm font-medium hover:bg-gray-50 transition-colors"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 transition-colors"
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
import { useEnergyStore } from '@/stores/energy'
|
||||||
|
|
||||||
|
const energyStore = useEnergyStore()
|
||||||
|
|
||||||
|
// Modal states
|
||||||
|
const showNewOptimizationModal = ref(false)
|
||||||
|
const showScheduleModal = ref(false)
|
||||||
|
|
||||||
|
// Optimization settings state
|
||||||
|
const optimizations = ref({
|
||||||
|
hvac: {
|
||||||
|
predictive_temp: true,
|
||||||
|
occupancy_schedule: true,
|
||||||
|
weather_adjust: false
|
||||||
|
},
|
||||||
|
lighting: {
|
||||||
|
daylight_harvest: true,
|
||||||
|
motion_control: true,
|
||||||
|
circadian_sync: false
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
adaptive_access: false,
|
||||||
|
anomaly_detection: true,
|
||||||
|
predictive_maintenance: false
|
||||||
|
},
|
||||||
|
air_quality: {
|
||||||
|
co2_ventilation: true,
|
||||||
|
smart_filtration: true,
|
||||||
|
humidity_control: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mock data for active optimizations
|
||||||
|
const activeOptimizations = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'HVAC Temperature Optimization',
|
||||||
|
description: 'Predictive temperature control across all zones',
|
||||||
|
icon: '❄️',
|
||||||
|
statusColor: 'bg-green-100',
|
||||||
|
startTime: '2 hours ago',
|
||||||
|
impact: '-15.2% energy',
|
||||||
|
impactColor: 'text-green-600'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Smart Lighting Control',
|
||||||
|
description: 'Daylight harvesting for Conference Room A',
|
||||||
|
icon: '💡',
|
||||||
|
statusColor: 'bg-amber-100',
|
||||||
|
startTime: '45 minutes ago',
|
||||||
|
impact: '-8.7% energy',
|
||||||
|
impactColor: 'text-green-600'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'CO2-based Ventilation',
|
||||||
|
description: 'Adaptive air quality management',
|
||||||
|
icon: '💨',
|
||||||
|
statusColor: 'bg-blue-100',
|
||||||
|
startTime: '1 hour ago',
|
||||||
|
impact: '+2.1% comfort',
|
||||||
|
impactColor: 'text-blue-600'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Mock data for upcoming optimizations
|
||||||
|
const upcomingOptimizations = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Peak Load Management',
|
||||||
|
icon: '⚡',
|
||||||
|
rooms: ['All Zones'],
|
||||||
|
frequency: 'Daily',
|
||||||
|
nextRun: 'Today, 2:00 PM'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Night Mode Optimization',
|
||||||
|
icon: '🌙',
|
||||||
|
rooms: ['Office Floor 1', 'Office Floor 2'],
|
||||||
|
frequency: 'Daily',
|
||||||
|
nextRun: 'Today, 6:00 PM'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Weekend Energy Saving',
|
||||||
|
icon: '🏢',
|
||||||
|
rooms: ['Conference Rooms', 'Meeting Rooms'],
|
||||||
|
frequency: 'Weekly',
|
||||||
|
nextRun: 'Saturday, 8:00 AM'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Computed properties
|
||||||
|
const totalAIActions = computed(() => {
|
||||||
|
return Object.values(optimizations.value).reduce((total, category) => {
|
||||||
|
return total + Object.values(category).filter(Boolean).length
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const isOptimizationEnabled = (category: string, optimization: string) => {
|
||||||
|
const categorySettings = optimizations.value[category as keyof typeof optimizations.value]
|
||||||
|
if (!categorySettings) return false
|
||||||
|
return (categorySettings as any)[optimization] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleOptimization = (category: string, optimization: string) => {
|
||||||
|
const current = isOptimizationEnabled(category, optimization)
|
||||||
|
const categorySettings = optimizations.value[category as keyof typeof optimizations.value]
|
||||||
|
if (categorySettings) {
|
||||||
|
(categorySettings as any)[optimization] = !current
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate API call
|
||||||
|
console.log(`${current ? 'Disabled' : 'Enabled'} ${category}.${optimization}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pauseOptimization = (id: number) => {
|
||||||
|
const optimization = activeOptimizations.value.find(opt => opt.id === id)
|
||||||
|
if (optimization) {
|
||||||
|
console.log(`Pausing optimization: ${optimization.name}`)
|
||||||
|
// In a real app, this would make an API call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize connection
|
||||||
|
onMounted(() => {
|
||||||
|
if (!energyStore.isConnected) {
|
||||||
|
energyStore.connect('ws://192.168.1.73:8000/ws')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user