297 lines
6.5 KiB
TypeScript
297 lines
6.5 KiB
TypeScript
/**
|
|
* Vue Composable for API Integration
|
|
* Provides reactive API state management
|
|
*/
|
|
import { ref, reactive } from 'vue'
|
|
import {
|
|
sensorsApi,
|
|
roomsApi,
|
|
analyticsApi,
|
|
healthApi,
|
|
type SensorDevice,
|
|
type SensorType,
|
|
type SensorStatus,
|
|
type SensorMetadata,
|
|
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<SensorDevice[]>([])
|
|
const currentSensor = ref<SensorDevice | null>(null)
|
|
const sensorData = ref<DataResponse | null>(null)
|
|
|
|
const { handleApiCall } = useApi()
|
|
|
|
const fetchSensors = async (params?: {
|
|
room?: string
|
|
sensor_type?: SensorType
|
|
status?: SensorStatus
|
|
}) => {
|
|
const result = await handleApiCall(() => sensorsApi.getSensors(params), state)
|
|
if (result && result.sensors) {
|
|
sensors.value = result.sensors
|
|
}
|
|
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: SensorMetadata) => {
|
|
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,
|
|
}
|
|
}
|