Files
bakery-ia/frontend/src/api/services/external.service.ts

264 lines
6.7 KiB
TypeScript
Raw Normal View History

2025-08-12 18:17:30 +02:00
// frontend/src/api/services/external.service.ts
/**
* External Data Service
* Handles weather and traffic data operations for the external microservice
*/
import { apiClient } from '../client';
import { RequestTimeouts } from '../client/config';
// Align with backend WeatherDataResponse schema
export interface WeatherData {
date: string;
temperature?: number;
precipitation?: number;
humidity?: number;
wind_speed?: number;
pressure?: number;
description?: string;
source: string;
}
// Align with backend TrafficDataResponse schema
export interface TrafficData {
date: string;
traffic_volume?: number;
pedestrian_count?: number;
congestion_level?: string;
average_speed?: number;
source: string;
}
export interface WeatherForecast {
date: string;
temperature_min: number;
temperature_max: number;
temperature_avg: number;
precipitation: number;
description: string;
humidity?: number;
wind_speed?: number;
}
export class ExternalService {
/**
* Get Current Weather Data
*/
async getCurrentWeather(
tenantId: string,
lat: number,
lon: number
): Promise<WeatherData> {
try {
// ✅ FIX 1: Correct endpoint path with tenant ID
const endpoint = `/tenants/${tenantId}/weather/current`;
// ✅ FIX 2: Correct parameter names (latitude/longitude, not lat/lon)
const response = await apiClient.get(endpoint, {
params: {
latitude: lat, // Backend expects 'latitude'
longitude: lon // Backend expects 'longitude'
}
});
console.log('Weather API response:', response);
// Return backend response directly (matches WeatherData interface)
return response;
} catch (error) {
console.error('Failed to fetch weather from backend:', error);
// Fallback weather for Madrid (matching WeatherData schema)
return {
date: new Date().toISOString(),
temperature: 18,
description: 'Parcialmente nublado',
precipitation: 0,
humidity: 65,
wind_speed: 10,
source: 'fallback'
};
}
}
/**
* Get Weather Forecast
*/
async getWeatherForecast(
tenantId: string,
lat: number,
lon: number,
days: number = 7
): Promise<WeatherForecast[]> {
try {
// Fix: Use POST with JSON body as expected by backend
const response = await apiClient.post(`/tenants/${tenantId}/weather/forecast`, {
latitude: lat,
longitude: lon,
days: days
});
// Handle response format
if (Array.isArray(response)) {
return response;
} else if (response && response.forecasts) {
return response.forecasts;
} else {
console.warn('Unexpected weather forecast response format:', response);
return [];
}
} catch (error) {
console.error('Failed to fetch weather forecast:', error);
return [];
}
}
/**
* Get Historical Weather Data
*/
async getHistoricalWeather(
tenantId: string,
lat: number,
lon: number,
startDate: string,
endDate: string
): Promise<WeatherData[]> {
try {
// Fix: Use POST with JSON body as expected by backend
const response = await apiClient.post(`/tenants/${tenantId}/weather/historical`, {
latitude: lat,
longitude: lon,
start_date: startDate,
end_date: endDate
});
// Return backend response directly (matches WeatherData interface)
return Array.isArray(response) ? response : response.data || [];
} catch (error) {
console.error('Failed to fetch historical weather:', error);
return [];
}
}
/**
* Get Current Traffic Data
*/
async getCurrentTraffic(
tenantId: string,
lat: number,
lon: number
): Promise<TrafficData> {
try {
const response = await apiClient.get(`/tenants/${tenantId}/traffic/current`, {
params: {
latitude: lat,
longitude: lon
}
});
// Return backend response directly (matches TrafficData interface)
return response;
} catch (error) {
console.error('Failed to fetch traffic data:', error);
// Fallback traffic data (matching TrafficData schema)
return {
date: new Date().toISOString(),
traffic_volume: 50,
pedestrian_count: 25,
congestion_level: 'medium',
average_speed: 30,
source: 'fallback'
};
}
}
/**
* Get Traffic Forecast
*/
async getTrafficForecast(
tenantId: string,
lat: number,
lon: number,
hours: number = 24
): Promise<TrafficData[]> {
try {
// Fix: Use POST with JSON body as expected by backend
const response = await apiClient.post(`/tenants/${tenantId}/traffic/forecast`, {
latitude: lat,
longitude: lon,
hours: hours
});
// Return backend response directly (matches TrafficData interface)
return Array.isArray(response) ? response : response.data || [];
} catch (error) {
console.error('Failed to fetch traffic forecast:', error);
return [];
}
}
/**
* Get Historical Traffic Data
*/
async getHistoricalTraffic(
tenantId: string,
lat: number,
lon: number,
startDate: string,
endDate: string
): Promise<TrafficData[]> {
try {
// Fix: Use POST with JSON body as expected by backend
const response = await apiClient.post(`/tenants/${tenantId}/traffic/historical`, {
latitude: lat,
longitude: lon,
start_date: startDate,
end_date: endDate
});
// Return backend response directly (matches TrafficData interface)
return Array.isArray(response) ? response : response.data || [];
} catch (error) {
console.error('Failed to fetch historical traffic:', error);
return [];
}
}
/**
* Test External Service Connectivity
*/
async testConnectivity(tenantId: string): Promise<{
weather: boolean;
traffic: boolean;
overall: boolean;
}> {
const results = {
weather: false,
traffic: false,
overall: false
};
try {
// Test weather service
await this.getCurrentWeather(tenantId, 40.4168, -3.7038); // Madrid coordinates
results.weather = true;
} catch (error) {
console.warn('Weather service connectivity test failed:', error);
}
try {
// Test traffic service
await this.getCurrentTraffic(tenantId, 40.4168, -3.7038); // Madrid coordinates
results.traffic = true;
} catch (error) {
console.warn('Traffic service connectivity test failed:', error);
}
results.overall = results.weather && results.traffic;
return results;
}
}
export const externalService = new ExternalService();