Add crop zoning feature with localization support and new dependencies
- Introduced crop zoning functionality, including a new section in the navigation menu. - Added Persian translations for crop zoning-related UI elements. - Updated package.json and package-lock.json to include new dependencies: @mapbox/mapbox-gl-draw and various @turf packages for geospatial calculations. - Enhanced global styles for crop zoning tooltips to improve user experience.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useCallback } from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import Box from '@mui/material/Box'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import Button from '@mui/material/Button'
|
||||
import CropZoningMap from './CropZoningMap'
|
||||
import ZoneLegend from './ZoneLegend'
|
||||
import LayerControl from './LayerControl'
|
||||
import ZoneDetailPanel from './ZoneDetailPanel'
|
||||
import type { LayerType } from './cropZoningTypes'
|
||||
import type { ZoneFeatureProperties } from './cropZoningTypes'
|
||||
import type { MapDrawGeoJSON } from './CropZoningMap'
|
||||
|
||||
const MapComponent = dynamic(() => Promise.resolve(CropZoningMap), {
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<Box className='flex items-center justify-center bs-full min-bs-[400px] rounded-xl bg-action-hover'>
|
||||
<CircularProgress size={48} />
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
|
||||
export default function CropZoningWrapper() {
|
||||
const t = useTranslations('cropZoning')
|
||||
const [areaGeoJson, setAreaGeoJson] = useState<MapDrawGeoJSON>(null)
|
||||
const [activeLayer, setActiveLayer] = useState<LayerType>('crops')
|
||||
const [selectedZone, setSelectedZone] = useState<ZoneFeatureProperties | null>(null)
|
||||
const [panelOpen, setPanelOpen] = useState(false)
|
||||
const [optimizationKey, setOptimizationKey] = useState(0)
|
||||
|
||||
const handleAreaChange = useCallback((geojson: MapDrawGeoJSON) => {
|
||||
setAreaGeoJson(geojson)
|
||||
}, [])
|
||||
|
||||
const handleZoneClick = useCallback((zone: ZoneFeatureProperties) => {
|
||||
setSelectedZone(zone)
|
||||
setPanelOpen(true)
|
||||
}, [])
|
||||
|
||||
const handleOptimize = useCallback(() => {
|
||||
setOptimizationKey(k => k + 1)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Box className='relative is-full min-bs-[calc(100vh-120px)] rounded-xl overflow-hidden'>
|
||||
<Box className='absolute inset-0 z-0'>
|
||||
<MapComponent
|
||||
center={[35.6892, 51.389]}
|
||||
zoom={13}
|
||||
height='100%'
|
||||
activeLayer={activeLayer}
|
||||
onAreaChange={handleAreaChange}
|
||||
onZoneClick={handleZoneClick}
|
||||
optimizationKey={optimizationKey}
|
||||
className='min-bs-[400px]'
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<LayerControl activeLayer={activeLayer} onLayerChange={setActiveLayer} />
|
||||
|
||||
{areaGeoJson && (
|
||||
<>
|
||||
<ZoneLegend />
|
||||
<Box className='absolute top-16 end-4 z-[1000]'>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
size='medium'
|
||||
startIcon={<i className='tabler-refresh text-xl' />}
|
||||
onClick={handleOptimize}
|
||||
className='rounded-xl shadow-lg'
|
||||
>
|
||||
{t('optimizeAgain')}
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
|
||||
<ZoneDetailPanel
|
||||
open={panelOpen}
|
||||
onClose={() => setPanelOpen(false)}
|
||||
zone={selectedZone}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user