feat: simplify regional workbench language
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 23:15:50 +02:00
parent 0381fdd636
commit b50b250f72
18 changed files with 292 additions and 97 deletions
@@ -1,6 +1,6 @@
import type { Dispatch, FormEvent, SetStateAction } from 'react'
import type { AreaRead, DatasetCreateResponse } from '../../types'
import { getDatasetDisplayName } from '../../lib/datasetDisplay'
import { getDatasetDisplayName, getDatasetSourceDisplayName } from '../../lib/datasetDisplay'
interface DatasetFormState {
datasetType: string
@@ -63,6 +63,9 @@ function normalizeDatasetRole(dataset: DatasetCreateResponse): 'reference' | 'ca
if (dataset.dataset_role === 'reference') {
return 'reference'
}
if (dataset.dataset_role === 'source') {
return 'source'
}
if (dataset.dataset_role === 'derived' || isVectorDatasetType(dataset.dataset_type)) {
return 'candidate'
}
@@ -76,7 +79,7 @@ function datasetRoleLabel(role: string): string {
if (role === 'candidate') {
return 'Analyse-resultaat'
}
return 'Eigen bron'
return 'Basisbron'
}
function datasetActionHint(dataset: DatasetCreateResponse, role: string): string {
@@ -92,6 +95,19 @@ function datasetActionHint(dataset: DatasetCreateResponse, role: string): string
return 'Ingeladen gegevensbron voor verdere analyse.'
}
function formatObservationDate(value: string | null | undefined): string {
if (!value) return 'huidige toestand'
const date = new Date(value)
if (Number.isNaN(date.getTime())) return value
return new Intl.DateTimeFormat('nl-BE', { day: 'numeric', month: 'short', year: 'numeric' }).format(date)
}
function datasetKindLabel(dataset: DatasetCreateResponse): string {
if (dataset.dataset_type === 'raster') return 'Luchtbeeld'
if (isVectorDatasetType(dataset.dataset_type)) return 'Kaartlaag'
return 'Gegevensbron'
}
export function DatasetPanel({
selectedProjectId,
selectedDatasetId,
@@ -107,8 +123,24 @@ export function DatasetPanel({
onOpenDatasetInMap,
onOpenDatasetExport,
}: DatasetPanelProps) {
const readyDatasets = datasets.filter((dataset) => dataset.status === 'ready').length
const selectedDataset = datasets.find((dataset) => dataset.id === selectedDatasetId)
const latestDatasetBySeries = new Map<string, DatasetCreateResponse>()
datasets.forEach((dataset) => {
if (!dataset.temporal_series_key) return
const current = latestDatasetBySeries.get(dataset.temporal_series_key)
const currentTimestamp = current?.observed_at ? Date.parse(current.observed_at) : Number.NEGATIVE_INFINITY
const candidateTimestamp = dataset.observed_at ? Date.parse(dataset.observed_at) : Number.NEGATIVE_INFINITY
if (!current || candidateTimestamp > currentTimestamp) {
latestDatasetBySeries.set(dataset.temporal_series_key, dataset)
}
})
const primaryDatasets = datasets.filter(
(dataset) => !dataset.temporal_series_key || latestDatasetBySeries.get(dataset.temporal_series_key)?.id === dataset.id,
)
const historicalDatasets = datasets.filter(
(dataset) => dataset.temporal_series_key && latestDatasetBySeries.get(dataset.temporal_series_key)?.id !== dataset.id,
)
const readyDatasets = primaryDatasets.filter((dataset) => dataset.status === 'ready').length
const roleSummaries = [
{
key: 'selected',
@@ -120,21 +152,21 @@ export function DatasetPanel({
{
key: 'reference',
label: 'Referentie',
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'reference').length,
count: primaryDatasets.filter((dataset) => normalizeDatasetRole(dataset) === 'reference').length,
hint: 'Officieel',
className: 'dataset-role-reference',
},
{
key: 'candidate',
label: 'Resultaat',
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'candidate').length,
count: primaryDatasets.filter((dataset) => normalizeDatasetRole(dataset) === 'candidate').length,
hint: 'Afgeleid',
className: 'dataset-role-candidate',
},
{
key: 'source',
label: 'Eigen bron',
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'source').length,
label: 'Basisbron',
count: primaryDatasets.filter((dataset) => normalizeDatasetRole(dataset) === 'source').length,
hint: 'Ingeladen',
className: 'dataset-role-source',
},
@@ -147,7 +179,7 @@ export function DatasetPanel({
<p className="eyebrow">Ingeladen gegevens</p>
<h2>Bronnen</h2>
</div>
<span className="count-pill">{readyDatasets}/{datasets.length} beschikbaar</span>
<span className="count-pill">{readyDatasets}/{primaryDatasets.length} bronnen beschikbaar</span>
</div>
<div className="data-selection-summary data-selection-summary-dataset">
@@ -165,17 +197,17 @@ export function DatasetPanel({
value={datasetForm.datasetType}
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, datasetType: event.target.value }))}
>
<option value="vector">vector</option>
<option value="geojson">geojson</option>
<option value="raster">raster</option>
<option value="vector">Kaartlaag</option>
<option value="geojson">GeoJSON-kaartlaag</option>
<option value="raster">Luchtbeeld of raster</option>
</select>
</label>
<label>
Bronnaam
Naam van de bron
<input
value={datasetForm.source}
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, source: event.target.value }))}
placeholder="user_upload"
placeholder="bijvoorbeeld eigen luchtbeeld"
/>
</label>
<label>
@@ -226,7 +258,7 @@ export function DatasetPanel({
<div className="data-panel-list-block dataset-catalog-block">
<p className="data-section-label">Beschikbare bronnen</p>
<ul className="dataset-list">
{datasets.map((dataset) => {
{primaryDatasets.map((dataset) => {
const datasetRole = normalizeDatasetRole(dataset)
const roleLabel = datasetRoleLabel(datasetRole)
return (
@@ -235,12 +267,12 @@ export function DatasetPanel({
<div>
<div className="dataset-card-kicker">
<span className={`dataset-role-badge dataset-role-${datasetRole}`}>{roleLabel}</span>
<span>{dataset.dataset_type}</span>
<span>{datasetKindLabel(dataset)}</span>
</div>
<strong className="dataset-card-title">{getDatasetDisplayName(dataset)}</strong>
<div className="entity-meta dataset-card-primary-meta">
<span>{(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} objecten</span>
<span>{dataset.source_name ?? dataset.source}</span>
<span>{getDatasetSourceDisplayName(dataset)} · {formatObservationDate(dataset.observed_at)}</span>
</div>
</div>
<span className={dataset.status === 'ready' ? 'status-badge status-badge-ready' : 'status-badge'}>
@@ -305,6 +337,28 @@ export function DatasetPanel({
)
})}
</ul>
{historicalDatasets.length > 0 ? (
<details className="dataset-history-disclosure">
<summary>
<span>Historische meetmomenten</span>
<strong>{historicalDatasets.length} oudere lagen</strong>
</summary>
<ul className="dataset-history-list">
{historicalDatasets.map((dataset) => (
<li key={dataset.id}>
<div>
<strong>{getDatasetDisplayName(dataset)}</strong>
<span>{formatObservationDate(dataset.observed_at)} · {(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} objecten</span>
</div>
<div className="panel-action-row">
<button className="secondary-action" type="button" onClick={() => onOpenDatasetInMap(dataset)}>Kaart</button>
<button className="secondary-action" type="button" onClick={() => onOpenDatasetExport(dataset)}>Downloaden</button>
</div>
</li>
))}
</ul>
</details>
) : null}
</div>
</section>
)