Files
sa4cps-frontend/src/composables/useApi.ts
rafaeldpsilva c3364cc422 format
2025-12-20 00:17:21 +00:00

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,
}
}