Add API service layer, authentication store, and composables

- Implement API service modules for sensors, rooms, analytics, health,
and auth - Add Pinia auth store for JWT token management and validation
- Create Vue composables for API integration and state management -
Update settings and AI optimization views for code style and connection
URLs - Add test-websocket.html for local WebSocket testing
This commit is contained in:
rafaeldpsilva
2025-09-18 14:29:36 +01:00
parent 32c63628b6
commit faed09d3b6
10 changed files with 1498 additions and 114 deletions

View File

@@ -0,0 +1,119 @@
<template>
<div class="auth-status" :class="authStatusClass">
<div class="auth-status__indicator">
<span class="auth-status__dot" :class="statusDotClass"></span>
<span class="auth-status__text">{{ statusText }}</span>
</div>
<div v-if="authStore.timeUntilExpiry" class="auth-status__expiry">
Token expires in: {{ formatTimeUntilExpiry() }}
</div>
<div v-if="authStore.error" class="auth-status__error">
Auth Error: {{ authStore.error }}
</div>
<button
v-if="!authStore.isAuthenticated"
@click="handleReauth"
:disabled="authStore.isLoading"
class="auth-status__retry-btn"
>
{{ authStore.isLoading ? 'Authenticating...' : 'Retry Authentication' }}
</button>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
const authStatusClass = computed(() => ({
'auth-status--authenticated': authStore.isAuthenticated,
'auth-status--error': !authStore.isAuthenticated || authStore.error,
'auth-status--loading': authStore.isLoading
}))
const statusDotClass = computed(() => ({
'auth-status__dot--green': authStore.isAuthenticated && !authStore.error,
'auth-status__dot--red': !authStore.isAuthenticated || authStore.error,
'auth-status__dot--yellow': authStore.isLoading
}))
const statusText = computed(() => {
if (authStore.isLoading) return 'Authenticating...'
if (authStore.isAuthenticated) return 'Authenticated'
return 'Not authenticated'
})
function formatTimeUntilExpiry(): string {
const time = authStore.timeUntilExpiry
if (!time) return 'Unknown'
if (time.hours > 0) {
return `${time.hours}h ${time.minutes}m`
} else {
return `${time.minutes}m`
}
}
async function handleReauth() {
await authStore.generateToken()
}
</script>
<style scoped lang="scss">
.auth-status {
@apply text-xs bg-gray-50 p-2 rounded border;
&--authenticated {
@apply bg-green-50 border-green-200 text-green-800;
}
&--error {
@apply bg-red-50 border-red-200 text-red-800;
}
&--loading {
@apply bg-yellow-50 border-yellow-200 text-yellow-800;
}
&__indicator {
@apply flex items-center gap-1 mb-1;
}
&__dot {
@apply w-2 h-2 rounded-full;
&--green {
@apply bg-green-500;
}
&--red {
@apply bg-red-500;
}
&--yellow {
@apply bg-yellow-500;
}
}
&__text {
@apply font-medium;
}
&__expiry {
@apply text-gray-600 mb-1;
}
&__error {
@apply text-red-600 text-xs mb-2;
}
&__retry-btn {
@apply bg-blue-500 text-white px-2 py-1 rounded text-xs hover:bg-blue-600 disabled:opacity-50;
}
}
</style>