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:
341
src/composables/useApi.ts
Normal file
341
src/composables/useApi.ts
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* Vue Composable for API Integration
|
||||
* Provides reactive API state management
|
||||
*/
|
||||
import { ref, reactive } from 'vue'
|
||||
import {
|
||||
sensorsApi,
|
||||
roomsApi,
|
||||
analyticsApi,
|
||||
healthApi,
|
||||
type SensorInfo,
|
||||
type RoomInfo,
|
||||
type RoomData,
|
||||
type AnalyticsSummary,
|
||||
type EnergyTrends,
|
||||
type RoomComparison,
|
||||
type SystemEvent,
|
||||
type HealthCheck,
|
||||
type SystemStatus,
|
||||
type DataQuery,
|
||||
type DataResponse
|
||||
} from '@/services'
|
||||
|
||||
interface ApiState {
|
||||
loading: boolean
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export function useApi() {
|
||||
// Global API state
|
||||
const globalState = reactive<ApiState>({
|
||||
loading: false,
|
||||
error: null
|
||||
})
|
||||
|
||||
// Helper to handle API calls with state management
|
||||
async function handleApiCall<T>(
|
||||
apiCall: () => Promise<T>,
|
||||
localState?: { loading: boolean; error: string | null }
|
||||
): Promise<T | null> {
|
||||
const state = localState || globalState
|
||||
|
||||
state.loading = true
|
||||
state.error = null
|
||||
|
||||
try {
|
||||
const result = await apiCall()
|
||||
return result
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
state.error = errorMessage
|
||||
console.error('API call failed:', errorMessage)
|
||||
return null
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
globalState,
|
||||
handleApiCall
|
||||
}
|
||||
}
|
||||
|
||||
// Sensors API composable
|
||||
export function useSensorsApi() {
|
||||
const state = reactive<ApiState>({
|
||||
loading: false,
|
||||
error: null
|
||||
})
|
||||
|
||||
const sensors = ref<SensorInfo[]>([])
|
||||
const currentSensor = ref<SensorInfo | null>(null)
|
||||
const sensorData = ref<DataResponse | null>(null)
|
||||
|
||||
const { handleApiCall } = useApi()
|
||||
|
||||
const fetchSensors = async (params?: {
|
||||
room?: string
|
||||
sensor_type?: any
|
||||
status?: any
|
||||
}) => {
|
||||
const result = await handleApiCall(
|
||||
() => sensorsApi.getSensors(params),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
sensors.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchSensor = async (sensorId: string) => {
|
||||
const result = await handleApiCall(
|
||||
() => sensorsApi.getSensor(sensorId),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
currentSensor.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchSensorData = async (
|
||||
sensorId: string,
|
||||
params?: {
|
||||
start_time?: number
|
||||
end_time?: number
|
||||
limit?: number
|
||||
offset?: number
|
||||
}
|
||||
) => {
|
||||
const result = await handleApiCall(
|
||||
() => sensorsApi.getSensorData(sensorId, params),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
sensorData.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const queryData = async (query: DataQuery) => {
|
||||
return handleApiCall(
|
||||
() => sensorsApi.queryData(query),
|
||||
state
|
||||
)
|
||||
}
|
||||
|
||||
const updateSensorMetadata = async (
|
||||
sensorId: string,
|
||||
metadata: Record<string, any>
|
||||
) => {
|
||||
return handleApiCall(
|
||||
() => sensorsApi.updateSensorMetadata(sensorId, metadata),
|
||||
state
|
||||
)
|
||||
}
|
||||
|
||||
const deleteSensor = async (sensorId: string) => {
|
||||
return handleApiCall(
|
||||
() => sensorsApi.deleteSensor(sensorId),
|
||||
state
|
||||
)
|
||||
}
|
||||
|
||||
const exportData = async (params: {
|
||||
start_time: number
|
||||
end_time: number
|
||||
sensor_ids?: string
|
||||
format?: 'json' | 'csv'
|
||||
}) => {
|
||||
return handleApiCall(
|
||||
() => sensorsApi.exportData(params),
|
||||
state
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
sensors,
|
||||
currentSensor,
|
||||
sensorData,
|
||||
fetchSensors,
|
||||
fetchSensor,
|
||||
fetchSensorData,
|
||||
queryData,
|
||||
updateSensorMetadata,
|
||||
deleteSensor,
|
||||
exportData
|
||||
}
|
||||
}
|
||||
|
||||
// Rooms API composable
|
||||
export function useRoomsApi() {
|
||||
const state = reactive<ApiState>({
|
||||
loading: false,
|
||||
error: null
|
||||
})
|
||||
|
||||
const rooms = ref<RoomInfo[]>([])
|
||||
const currentRoomData = ref<RoomData | null>(null)
|
||||
|
||||
const { handleApiCall } = useApi()
|
||||
|
||||
const fetchRooms = async () => {
|
||||
const result = await handleApiCall(
|
||||
() => roomsApi.getRooms(),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
rooms.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchRoomData = async (
|
||||
roomName: string,
|
||||
params?: {
|
||||
start_time?: number
|
||||
end_time?: number
|
||||
limit?: number
|
||||
}
|
||||
) => {
|
||||
const result = await handleApiCall(
|
||||
() => roomsApi.getRoomData(roomName, params),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
currentRoomData.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
rooms,
|
||||
currentRoomData,
|
||||
fetchRooms,
|
||||
fetchRoomData
|
||||
}
|
||||
}
|
||||
|
||||
// Analytics API composable
|
||||
export function useAnalyticsApi() {
|
||||
const state = reactive<ApiState>({
|
||||
loading: false,
|
||||
error: null
|
||||
})
|
||||
|
||||
const summary = ref<AnalyticsSummary | null>(null)
|
||||
const trends = ref<EnergyTrends | null>(null)
|
||||
const roomComparison = ref<RoomComparison | null>(null)
|
||||
const events = ref<SystemEvent[]>([])
|
||||
|
||||
const { handleApiCall } = useApi()
|
||||
|
||||
const fetchAnalyticsSummary = async (hours: number = 24) => {
|
||||
const result = await handleApiCall(
|
||||
() => analyticsApi.getAnalyticsSummary(hours),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
summary.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchEnergyTrends = async (hours: number = 168) => {
|
||||
const result = await handleApiCall(
|
||||
() => analyticsApi.getEnergyTrends(hours),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
trends.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchRoomComparison = async (hours: number = 24) => {
|
||||
const result = await handleApiCall(
|
||||
() => analyticsApi.getRoomComparison(hours),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
roomComparison.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchEvents = async (params?: {
|
||||
severity?: string
|
||||
event_type?: string
|
||||
hours?: number
|
||||
limit?: number
|
||||
}) => {
|
||||
const result = await handleApiCall(
|
||||
() => analyticsApi.getEvents(params),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
events.value = result.events
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
summary,
|
||||
trends,
|
||||
roomComparison,
|
||||
events,
|
||||
fetchAnalyticsSummary,
|
||||
fetchEnergyTrends,
|
||||
fetchRoomComparison,
|
||||
fetchEvents
|
||||
}
|
||||
}
|
||||
|
||||
// Health API composable
|
||||
export function useHealthApi() {
|
||||
const state = reactive<ApiState>({
|
||||
loading: false,
|
||||
error: null
|
||||
})
|
||||
|
||||
const health = ref<HealthCheck | null>(null)
|
||||
const status = ref<SystemStatus | null>(null)
|
||||
|
||||
const { handleApiCall } = useApi()
|
||||
|
||||
const fetchHealth = async () => {
|
||||
const result = await handleApiCall(
|
||||
() => healthApi.getHealth(),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
health.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const fetchStatus = async () => {
|
||||
const result = await handleApiCall(
|
||||
() => healthApi.getStatus(),
|
||||
state
|
||||
)
|
||||
if (result) {
|
||||
status.value = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
health,
|
||||
status,
|
||||
fetchHealth,
|
||||
fetchStatus
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user