+
${cropLabel}
+
درصد تطابق: ${props.matchPercent}%
+
نیاز آب: ${props.waterNeed}
+
سود تخمینی: ${props.estimatedProfit}
+
+ `
+ layer.bindTooltip(tooltipContent, {
+ sticky: true,
+ className: 'zone-tooltip',
+ direction: 'top',
+ offset: [0, -8]
+ })
+ layer.on('click', () => onZoneClick?.(props))
+ }
+ })
+
+ geoJsonLayer.addTo(map)
+ zonesLayerRef.current = geoJsonLayer
+
+ let idx = 0
+ geoJsonLayer.eachLayer((layer: L.Layer) => {
+ const leafLayer = layer as L.Polygon
+ leafLayer.setStyle({ fillOpacity: 0 })
+ const index = idx++
+ const targetOpacity = 0.5
+ const delay = Math.min(index * 30, 600)
+ setTimeout(() => {
+ leafLayer.setStyle({ fillOpacity: targetOpacity })
+ }, delay)
+ })
+ },
+ [activeLayer, onZoneClick]
+ )
+
+ useEffect(() => {
+ if (typeof window === 'undefined' || !mapRef.current) return
+
+ let isMounted = true
+ let cleanupFn: (() => void) | null = null
+
+ const initMap = async () => {
+ const L = (await import('leaflet')).default
+ await import('leaflet-draw')
+ ;(window as unknown as { L: typeof L }).L = L
+
+ if (!isMounted || !mapRef.current || mapInstanceRef.current) return
+
+ const map = L.map(mapRef.current).setView(center, zoom)
+
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+ attribution: '© OpenStreetMap'
+ }).addTo(map)
+
+ const drawnItems = L.featureGroup().addTo(map)
+ drawnItemsRef.current = drawnItems
+
+ const drawControl = new L.Control.Draw({
+ position: 'topright',
+ draw: {
+ polygon: { shapeOptions: { color: '#3388ff' } },
+ rectangle: { shapeOptions: { color: '#3388ff' } },
+ circle: false,
+ circlemarker: false,
+ marker: false,
+ polyline: false
+ },
+ edit: { featureGroup: drawnItems, remove: true }
+ })
+
+ map.addControl(drawControl)
+ drawControlRef.current = drawControl
+
+ const getGeoJsonFromDrawn = (): MapDrawGeoJSON => {
+ const geojson = drawnItems.toGeoJSON()
+ if (geojson.type === 'FeatureCollection' && geojson.features.length > 0) {
+ return geojson.features[0] as unknown as MapDrawGeoJSON
+ }
+ return null
+ }
+
+ const emitAndRender = () => {
+ const geojson = getGeoJsonFromDrawn()
+ onAreaChange?.(geojson)
+ if (geojson && geojson.geometry && (geojson.geometry as { type: string }).type === 'Polygon') {
+ renderZones(map, geojson as Feature