MCPcopy Create free account
hub / github.com/Thanas-R/Virdis / FieldDetailView

Function FieldDetailView

src/components/FieldDetailView.tsx:216–756  ·  view source on GitHub ↗
({ field, onBack, onEditBoundary }: FieldDetailViewProps)

Source from the content-addressed store, hash-verified

214const TEXTURE_COLORS = { sand: "#EAB947", silt: "#A0785A", clay: "#854F0B" };
215
216const FieldDetailView = ({ field, onBack, onEditBoundary }: FieldDetailViewProps) => {
217 const [weather, setWeather] = useState<FieldWeather | null>(null);
218 const [loading, setLoading] = useState(true);
219 const [ndviStats, setNdviStats] = useState<NdviStats | null>(null);
220 const [ndviLoading, setNdviLoading] = useState(false);
221 const [aiAnalysis, setAiAnalysis] = useState<string>("");
222 const [aiLoading, setAiLoading] = useState(false);
223 const [showAnalysis, setShowAnalysis] = useState(false);
224 const [soilData, setSoilData] = useState<SoilData | null>(null);
225 const [soilLoading, setSoilLoading] = useState(false);
226 const [aqiData, setAqiData] = useState<AqiData | null>(null);
227 const [soilMoisture, setSoilMoisture] = useState<number | null>(null);
228
229 const areaAcres = haToAcres(field.area);
230 const urban = isUrbanField(field);
231
232 const fieldCenter = useMemo(() => {
233 const coords = field.coordinates[0];
234 return {
235 lat: coords.reduce((s, c) => s + c[1], 0) / coords.length,
236 lng: coords.reduce((s, c) => s + c[0], 0) / coords.length,
237 };
238 }, [field]);
239
240 // Fetch weather + AQI + soil moisture
241 useEffect(() => {
242 const fetchAll = async () => {
243 setLoading(true);
244 const { lat, lng } = fieldCenter;
245 try {
246 const [weatherRes, aqiRes, soilMoistRes] = await Promise.all([
247 fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}&current=temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code`),
248 fetch(`https://air-quality-api.open-meteo.com/v1/air-quality?latitude=${lat}&longitude=${lng}&current=pm2_5,pm10,european_aqi,us_aqi`),
249 fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}&hourly=soil_moisture_0_to_7cm&forecast_days=1`),
250 ]);
251 const [wData, aqData, smData] = await Promise.all([weatherRes.json(), aqiRes.json(), soilMoistRes.json()]);
252 setWeather(wData.current || null);
253 if (aqData.current) setAqiData(aqData.current);
254 if (smData.hourly?.soil_moisture_0_to_7cm) {
255 const vals = smData.hourly.soil_moisture_0_to_7cm.filter((v: any) => v != null);
256 if (vals.length) setSoilMoisture(Math.round(vals[vals.length - 1] * 1000) / 10);
257 }
258 } catch { setWeather(null); }
259 finally { setLoading(false); }
260 };
261 fetchAll();
262 }, [field, fieldCenter]);
263
264 // Fetch soil data
265 useEffect(() => {
266 const cached = getFreshLocalCacheValue<SoilData>(SOIL_CACHE_KEY, field.id, QUERY_CACHE_TTL_MS);
267 if (cached) { setSoilData(cached); return; }
268 const fetchSoil = async () => {
269 setSoilLoading(true);
270 try {
271 const data = await invokeWithRetry<any>(
272 "soil-data",
273 { lat: fieldCenter.lat, lon: fieldCenter.lng },

Callers

nothing calls this directly

Calls 12

haToAcresFunction · 0.90
getFreshLocalCacheValueFunction · 0.90
isUrbanFieldFunction · 0.85
fetchAllFunction · 0.85
fetchNdviStatsFunction · 0.85
getCacheFunction · 0.85
splitAnalysisBlocksFunction · 0.85
waterStressLabelFunction · 0.85
ndviColorFunction · 0.85
ndviLabelFunction · 0.85
fetchSoilFunction · 0.70
getAqiLabelFunction · 0.70

Tested by

no test coverage detected