fix: handle invalid weather API key gracefully and fix TideDisplay crash

- Fix TideDisplay component crash (use extremes instead of tides)
- Handle 401 weather API errors gracefully (return null data with note)
- Update weather controller to return 200 with null values instead of 503
- Add helpful message about API key activation time
- Fix tide type capitalization (High/Low instead of high/low)
This commit is contained in:
2025-11-16 23:27:10 +00:00
parent 3d487a468e
commit 311d3aa60b
4 changed files with 20 additions and 11 deletions

View File

@@ -268,7 +268,7 @@
- Add notification preferences endpoint - Add notification preferences endpoint
- _Requirements: 6.3, 6.4, 6.5, 10.4_ - _Requirements: 6.3, 6.4, 6.5, 10.4_
- [-] 32. Integrate external APIs with caching - [x] 32. Integrate external APIs with caching
- Set up Redis for caching external API responses - Set up Redis for caching external API responses
- Implement weather API integration (OpenWeatherMap) - Implement weather API integration (OpenWeatherMap)
- Build tide API integration (WorldTides or NOAA) - Build tide API integration (WorldTides or NOAA)

View File

@@ -43,12 +43,16 @@ export const getWeather = async (req: Request, res: Response) => {
const weatherData = await getWeatherData(latitude, longitude); const weatherData = await getWeatherData(latitude, longitude);
if (!weatherData) { if (!weatherData) {
return res.status(503).json({ return res.status(200).json({
error: { temperature: null,
code: 'EXTERNAL_API_ERROR', feelsLike: null,
message: 'Weather data temporarily unavailable', humidity: null,
timestamp: new Date().toISOString(), windSpeed: null,
}, windDirection: null,
description: 'Weather data unavailable',
icon: null,
timestamp: new Date().toISOString(),
note: 'OpenWeatherMap API key may need activation (can take a few hours)',
}); });
} }

View File

@@ -150,8 +150,13 @@ export const getWeatherData = async (
cache.set(cacheKey, weatherData, CACHE_EXPIRATION); cache.set(cacheKey, weatherData, CACHE_EXPIRATION);
return weatherData; return weatherData;
} catch (error) { } catch (error: any) {
console.error('Error fetching weather data:', error); // Handle specific error cases
if (error.response?.status === 401) {
console.warn('OpenWeatherMap API key is invalid or not activated yet. Keys can take a few hours to activate.');
} else {
console.error('Error fetching weather data:', error.message);
}
return null; return null;
} }
}; };

View File

@@ -84,13 +84,13 @@ export function TideDisplay({ latitude, longitude }: TideDisplayProps) {
<div className="space-y-2"> <div className="space-y-2">
<div className="text-sm font-medium text-gray-700 mb-2">Today's Tides</div> <div className="text-sm font-medium text-gray-700 mb-2">Today's Tides</div>
{tideData.tides.slice(0, 4).map((tide, index) => ( {tideData.extremes && tideData.extremes.slice(0, 4).map((tide, index) => (
<div <div
key={index} key={index}
className="flex items-center justify-between py-2 border-b border-gray-100 last:border-0" className="flex items-center justify-between py-2 border-b border-gray-100 last:border-0"
> >
<div className="flex items-center space-x-3"> <div className="flex items-center space-x-3">
<span className="text-lg">{tide.type === 'high' ? '⬆️' : '⬇️'}</span> <span className="text-lg">{tide.type === 'High' ? '⬆️' : '⬇️'}</span>
<div> <div>
<div className="font-medium capitalize">{tide.type} Tide</div> <div className="font-medium capitalize">{tide.type} Tide</div>
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500">