feat: make Mol explorer map-first
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-14 13:21:53 +02:00
parent e340b7f1ec
commit 2958c25b6f
24 changed files with 1901 additions and 14 deletions
+4 -1
View File
@@ -21,6 +21,9 @@ export function useMapSelectionExtract({
useEffect(() => {
setMapSelectionBbox(null)
}, [selectedProjectId])
useEffect(() => {
setMapSelectionResult(null)
setMapSelectionError(null)
}, [selectedProjectId, selectedDataset?.id])
@@ -41,7 +44,7 @@ export function useMapSelectionExtract({
try {
const response = await datasetsApi.selectVectorFeatures(selectedProjectId, selectedDataset.id, {
bbox: { ...bbox, crs: 'EPSG:4326' },
limit: 250,
limit: 1000,
})
setMapSelectionResult(response)
return response
@@ -0,0 +1,80 @@
import { useEffect, useState } from 'react'
import { formatError } from '../lib/formatError'
import { datasetsApi } from '../services/api/datasets'
import type { DatasetCreateResponse, VectorSelectionBBox, VectorSelectionResponse } from '../types'
export interface MapThemeQuery<TThemeId extends string> {
themeId: TThemeId
dataset: DatasetCreateResponse
}
export interface MapThemeInsight<TThemeId extends string> extends MapThemeQuery<TThemeId> {
result: VectorSelectionResponse
}
export function useMapThemeSelectionInsights<TThemeId extends string>(
selectedProjectId: string | null,
) {
const [themeInsights, setThemeInsights] = useState<Array<MapThemeInsight<TThemeId>>>([])
const [themeInsightsLoading, setThemeInsightsLoading] = useState(false)
const [themeInsightsError, setThemeInsightsError] = useState<string | null>(null)
useEffect(() => {
setThemeInsights([])
setThemeInsightsError(null)
}, [selectedProjectId])
const clearThemeInsights = () => {
setThemeInsights([])
setThemeInsightsError(null)
}
const loadThemeInsights = async (
bbox: VectorSelectionBBox,
queries: Array<MapThemeQuery<TThemeId>>,
): Promise<Array<MapThemeInsight<TThemeId>>> => {
if (!selectedProjectId) {
setThemeInsights([])
setThemeInsightsError('Open eerst een project om de selectie te analyseren.')
return []
}
setThemeInsightsLoading(true)
setThemeInsightsError(null)
try {
const settled = await Promise.allSettled(
queries.map(async ({ themeId, dataset }) => ({
themeId,
dataset,
result: await datasetsApi.selectVectorFeatures(selectedProjectId, dataset.id, {
bbox,
limit: 1000,
}),
})),
)
const successful = settled.flatMap((item) => (item.status === 'fulfilled' ? [item.value] : []))
const failureCount = settled.length - successful.length
setThemeInsights(successful)
if (failureCount > 0) {
setThemeInsightsError(
`${failureCount} beschikbare databron${failureCount === 1 ? '' : 'nen'} kon niet worden bevraagd.`,
)
}
return successful
} catch (error) {
setThemeInsights([])
setThemeInsightsError(formatError(error, 'De gebiedsanalyse is mislukt.'))
return []
} finally {
setThemeInsightsLoading(false)
}
}
return {
themeInsights,
themeInsightsLoading,
themeInsightsError,
loadThemeInsights,
clearThemeInsights,
}
}
+11 -1
View File
@@ -31,7 +31,17 @@ export function useMapWorkspaceState({
if (areas.length === 0) {
setSelectedMapAreaId('')
} else if (!selectedMapAreaId || !areas.some((area) => area.id === selectedMapAreaId)) {
setSelectedMapAreaId(areas[0].id)
const municipalityArea = areas.find((area) => /gemeente mol|municipality/i.test(area.name))
if (municipalityArea) {
setSelectedMapAreaId(municipalityArea.id)
} else {
const largestArea = [...areas].sort((left, right) => (right.area_m2 ?? 0) - (left.area_m2 ?? 0))[0]
if (largestArea?.area_m2) {
setSelectedMapAreaId(largestArea.id)
} else {
setSelectedMapAreaId(areas[0].id)
}
}
}
}, [areas, selectedMapAreaId])