Add AIOptimizationView for managing AI optimizations
This commit is contained in:
@@ -46,17 +46,25 @@
|
||||
</router-link>
|
||||
</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">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
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>
|
||||
<span class="text-xs">Analytics</span>
|
||||
</a>
|
||||
<span class="text-xs">AI Optimize</span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
import SensorManagementView from '../views/SensorManagementView.vue'
|
||||
import AIOptimizationView from '../views/AIOptimizationView.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -15,6 +16,11 @@ const router = createRouter({
|
||||
name: 'sensors',
|
||||
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