diff --git a/backend/src/utils/validation.js b/backend/src/utils/validation.js index 7fe9191..4547629 100644 --- a/backend/src/utils/validation.js +++ b/backend/src/utils/validation.js @@ -44,7 +44,10 @@ const lawnSectionSchema = Joi.object({ area: Joi.number().positive().required(), polygonData: Joi.object(), grassType: Joi.string().max(100).allow(null, '').optional(), - soilType: Joi.string().max(100).allow(null, '').optional() + grassTypes: Joi.array().items(Joi.string().max(100)).allow(null).optional(), + soilType: Joi.string().max(100).allow(null, '').optional(), + captureMethod: Joi.string().valid('gps_points', 'gps_trace', 'tap').allow(null).optional(), + captureMeta: Joi.object().unknown(true).optional() }); // Equipment validation schemas diff --git a/frontend/src/pages/Properties/PropertyDetail.js b/frontend/src/pages/Properties/PropertyDetail.js index 991b3ec..21224cf 100644 --- a/frontend/src/pages/Properties/PropertyDetail.js +++ b/frontend/src/pages/Properties/PropertyDetail.js @@ -588,6 +588,8 @@ const PropertyDetail = () => { setGpsTracePoints([]); setGpsDistance(0); setGpsAccuracy(null); + // Stop passive watch if running (used for Points mode warmup) + if (gpsWatchId) { navigator.geolocation.clearWatch(gpsWatchId); setGpsWatchId(null); } }; const completeTracing = () => { @@ -1142,6 +1144,18 @@ const PropertyDetail = () => { if (gpsWatchId) { navigator.geolocation.clearWatch(gpsWatchId); setGpsWatchId(null); } clearGpsPoints(); setIsGPSPointsMode(true); + // Start passive GPS watch to warm up accuracy for Points mode + if (navigator.geolocation) { + const id = navigator.geolocation.watchPosition((pos)=>{ + const { latitude, longitude, accuracy } = pos.coords; + setGpsAccuracy(accuracy || null); + // Populate smoothing buffer without adding a point yet + try { addSampleAndSmooth(latitude, longitude, accuracy); } catch {} + }, (err)=>{ + console.warn('GPS warmup error', err?.message); + }, { enableHighAccuracy: true, maximumAge: 1000, timeout: 15000 }); + setGpsWatchId(id); + } }} >