From 4caba81599113c70f84ff046787a95f1a402dae6 Mon Sep 17 00:00:00 2001 From: Danilo Reyes Date: Sun, 28 Dec 2025 22:13:19 -0600 Subject: [PATCH] Enhance country data retrieval and error handling in WatchedMap component - Improved country code extraction logic to handle null values and prevent rendering errors. - Added error handling for API responses to ensure graceful degradation in case of failures. - Updated the logic for determining country codes from GeoJSON features to account for missing values. - Set default values for watched items and summary to avoid application crashes during data fetch failures. --- backend/app/services/sync.py | 17 ++++++++++++- frontend/src/components/WatchedMap.tsx | 34 +++++++++++++++++++++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/backend/app/services/sync.py b/backend/app/services/sync.py index f0ac679..0d8f99f 100644 --- a/backend/app/services/sync.py +++ b/backend/app/services/sync.py @@ -218,7 +218,22 @@ async def get_musicbrainz_artist_country(mbid: str) -> Optional[str]: ) if response.status_code == 200: data = response.json() - # Check area relations for country + + # First, check direct country field + if "country" in data and data["country"]: + country = data["country"] + if isinstance(country, str) and len(country) == 2: + return country.upper() + + # Second, check area.iso-3166-1-codes + if "area" in data and data["area"]: + area = data["area"] + if "iso-3166-1-codes" in area and area["iso-3166-1-codes"]: + codes = area["iso-3166-1-codes"] + if isinstance(codes, list) and len(codes) > 0: + return codes[0].upper() + + # Third, check area relations for country if "relations" in data: for relation in data["relations"]: if relation.get("type") == "origin" and "area" in relation: diff --git a/frontend/src/components/WatchedMap.tsx b/frontend/src/components/WatchedMap.tsx index ca480f5..4f70277 100644 --- a/frontend/src/components/WatchedMap.tsx +++ b/frontend/src/components/WatchedMap.tsx @@ -59,11 +59,25 @@ export default function WatchedMap() { fetch('/api/watched/summary'), ]) + if (!watchedRes.ok) { + throw new Error(`Watched API error: ${watchedRes.status}`) + } + if (!pinsRes.ok) { + throw new Error(`Pins API error: ${pinsRes.status}`) + } + if (!summaryRes.ok) { + throw new Error(`Summary API error: ${summaryRes.status}`) + } + setWatchedItems(await watchedRes.json()) setPins(await pinsRes.json()) setSummary(await summaryRes.json()) } catch (error) { console.error('Failed to fetch data:', error) + // Set empty defaults to prevent rendering errors + setWatchedItems([]) + setPins([]) + setSummary({}) } } @@ -123,7 +137,8 @@ export default function WatchedMap() { } } - const getCountryCount = (countryCode: string): number => { + const getCountryCount = (countryCode: string | null): number => { + if (!countryCode) return 0 const data = summary[countryCode] || {} return (data.movie || 0) + (data.show || 0) } @@ -133,7 +148,8 @@ export default function WatchedMap() { return Math.max(...counts, 1) } - const getCountryColor = (countryCode: string): string => { + const getCountryColor = (countryCode: string | null): string => { + if (!countryCode) return '#e0e0e0' const count = getCountryCount(countryCode) const maxCount = getMaxCount() if (count === 0) return '#e0e0e0' @@ -228,21 +244,27 @@ export default function WatchedMap() { { - const code = feature?.properties?.ISO_A2 || feature?.properties?.ISO_A3?.substring(0, 2) + const isoA2 = feature?.properties?.ISO_A2 + const isoA3 = feature?.properties?.ISO_A3 + const code = isoA2 || (isoA3 && typeof isoA3 === 'string' ? isoA3.substring(0, 2) : null) || null return { - fillColor: getCountryColor(code), + fillColor: getCountryColor(code || ''), fillOpacity: 0.7, color: '#666', weight: 1, } }} onEachFeature={(feature, layer) => { - const code = feature?.properties?.ISO_A2 || feature?.properties?.ISO_A3?.substring(0, 2) + const isoA2 = feature?.properties?.ISO_A2 + const isoA3 = feature?.properties?.ISO_A3 + const code = isoA2 || (isoA3 && typeof isoA3 === 'string' ? isoA3.substring(0, 2) : null) || null + if (!code) return + const count = getCountryCount(code) const data = summary[code] || {} layer.bindPopup(` - ${feature.properties.NAME || code}
+ ${feature.properties?.NAME || code}
Watched: ${count}
${data.movie ? `Movies: ${data.movie}
` : ''} ${data.show ? `Shows: ${data.show}` : ''}