format
This commit is contained in:
@@ -1,26 +1,25 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-2xl shadow-sm p-4">
|
||||
<h6 class="text-sm font-bold text-gray-500 mb-4">Room Overview</h6>
|
||||
|
||||
|
||||
<div class="space-y-4">
|
||||
<div v-if="roomsList.length === 0" class="text-center text-gray-500 py-8">
|
||||
No room data available. Connect sensors to see room metrics.
|
||||
</div>
|
||||
|
||||
|
||||
<div v-for="room in roomsList" :key="room.room" class="border border-gray-100 rounded-lg p-3">
|
||||
<!-- Room Header -->
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="font-medium text-gray-900">{{ room.room }}</h3>
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- CO2 Status Indicator -->
|
||||
<div
|
||||
class="w-3 h-3 rounded-full"
|
||||
:class="getCO2StatusColor(room.co2!.status)"
|
||||
></div>
|
||||
<div class="w-3 h-3 rounded-full" :class="getCO2StatusColor(room.co2!.status)"></div>
|
||||
<!-- Occupancy Indicator -->
|
||||
<div class="flex items-center gap-1 text-xs text-gray-500">
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
||||
<path
|
||||
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="capitalize">{{ room.occupancyEstimate }}</span>
|
||||
</div>
|
||||
@@ -32,15 +31,21 @@
|
||||
<!-- Energy -->
|
||||
<div class="bg-blue-50 rounded p-2">
|
||||
<div class="text-blue-600 font-medium">Energy</div>
|
||||
<div class="text-blue-900">{{ room.energy!.current.toFixed(2) }} {{ room.energy!.unit }}</div>
|
||||
<div class="text-blue-900">
|
||||
{{ room.energy!.current.toFixed(2) }} {{ room.energy!.unit }}
|
||||
</div>
|
||||
<div class="text-blue-600 text-xs">Total: {{ room.energy!.total.toFixed(2) }}</div>
|
||||
</div>
|
||||
|
||||
<!-- CO2 -->
|
||||
<div class="rounded p-2" :class="getCO2BackgroundColor(room.co2!.status)">
|
||||
<div class="font-medium" :class="getCO2TextColor(room.co2!.status)">CO2</div>
|
||||
<div :class="getCO2TextColor(room.co2!.status)">{{ Math.round(room.co2!.current) }} {{ room.co2!.unit }}</div>
|
||||
<div class="text-xs" :class="getCO2TextColor(room.co2!.status)">{{ room.co2!.status.toUpperCase() }}</div>
|
||||
<div :class="getCO2TextColor(room.co2!.status)">
|
||||
{{ Math.round(room.co2!.current) }} {{ room.co2!.unit }}
|
||||
</div>
|
||||
<div class="text-xs" :class="getCO2TextColor(room.co2!.status)">
|
||||
{{ room.co2!.status.toUpperCase() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +58,10 @@
|
||||
</div>
|
||||
|
||||
<!-- Summary Stats -->
|
||||
<div v-if="roomsList.length > 0" class="mt-4 pt-4 border-t border-gray-100 grid grid-cols-3 gap-4 text-center text-xs">
|
||||
<div
|
||||
v-if="roomsList.length > 0"
|
||||
class="mt-4 pt-4 border-t border-gray-100 grid grid-cols-3 gap-4 text-center text-xs"
|
||||
>
|
||||
<div>
|
||||
<div class="font-medium text-gray-900">{{ roomsList.length }}</div>
|
||||
<div class="text-gray-500">Rooms</div>
|
||||
@@ -78,7 +86,7 @@ const roomStore = useRoomStore()
|
||||
|
||||
const roomsList = computed(() => {
|
||||
return Array.from(roomStore.roomsData.values())
|
||||
.filter(room => room.energy && room.co2) // Only show rooms with both metrics
|
||||
.filter((room) => room.energy && room.co2) // Only show rooms with both metrics
|
||||
.sort((a, b) => a.room.localeCompare(b.room))
|
||||
})
|
||||
|
||||
@@ -94,31 +102,46 @@ const averageCO2 = computed(() => {
|
||||
|
||||
const getCO2StatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'good': return 'bg-green-500'
|
||||
case 'moderate': return 'bg-yellow-500'
|
||||
case 'poor': return 'bg-orange-500'
|
||||
case 'critical': return 'bg-red-500'
|
||||
default: return 'bg-gray-500'
|
||||
case 'good':
|
||||
return 'bg-green-500'
|
||||
case 'moderate':
|
||||
return 'bg-yellow-500'
|
||||
case 'poor':
|
||||
return 'bg-orange-500'
|
||||
case 'critical':
|
||||
return 'bg-red-500'
|
||||
default:
|
||||
return 'bg-gray-500'
|
||||
}
|
||||
}
|
||||
|
||||
const getCO2BackgroundColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'good': return 'bg-green-50'
|
||||
case 'moderate': return 'bg-yellow-50'
|
||||
case 'poor': return 'bg-orange-50'
|
||||
case 'critical': return 'bg-red-50'
|
||||
default: return 'bg-gray-50'
|
||||
case 'good':
|
||||
return 'bg-green-50'
|
||||
case 'moderate':
|
||||
return 'bg-yellow-50'
|
||||
case 'poor':
|
||||
return 'bg-orange-50'
|
||||
case 'critical':
|
||||
return 'bg-red-50'
|
||||
default:
|
||||
return 'bg-gray-50'
|
||||
}
|
||||
}
|
||||
|
||||
const getCO2TextColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'good': return 'text-green-700'
|
||||
case 'moderate': return 'text-yellow-700'
|
||||
case 'poor': return 'text-orange-700'
|
||||
case 'critical': return 'text-red-700'
|
||||
default: return 'text-gray-700'
|
||||
case 'good':
|
||||
return 'text-green-700'
|
||||
case 'moderate':
|
||||
return 'text-yellow-700'
|
||||
case 'poor':
|
||||
return 'text-orange-700'
|
||||
case 'critical':
|
||||
return 'text-red-700'
|
||||
default:
|
||||
return 'text-gray-700'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +150,7 @@ const formatTime = (timestamp: number) => {
|
||||
const now = new Date()
|
||||
const diffMs = now.getTime() - date.getTime()
|
||||
const diffSecs = Math.floor(diffMs / 1000)
|
||||
|
||||
|
||||
if (diffSecs < 60) {
|
||||
return `${diffSecs}s ago`
|
||||
} else if (diffSecs < 3600) {
|
||||
@@ -136,4 +159,4 @@ const formatTime = (timestamp: number) => {
|
||||
return date.toLocaleTimeString()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user