Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ declare module 'vue' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
TimeSeriesChart: typeof import('./src/components/TimeSeriesChart.vue')['default']
TreeHealthChart: typeof import('./src/components/TreeHealthChart.vue')['default']
}
}
120 changes: 108 additions & 12 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@
<div class="legend-items">
<div
v-for="item in legendItems"
:key="item.bronId"
:key="item.key"
class="legend-item"
:class="{
'legend-item--disabled': appStore.disabledCategories.has(
item.bronId
),
'legend-item--disabled': item.isTree
? appStore.disabledTrees
: appStore.disabledCategories.has(item.bronId),
}"
@click="appStore.toggleCategory(item.bronId)"
@click="onLegendItemClick(item)"
>
<div
v-if="!item.isTree"
class="legend-symbol"
:style="{
borderColor: appStore.disabledCategories.has(item.bronId)
Expand All @@ -46,6 +47,12 @@
opacity: appStore.disabledCategories.has(item.bronId) ? 0.5 : 1,
}"
/>
<v-icon
v-else
:color="appStore.disabledTrees ? '#9e9e9e' : item.color"
icon="mdi-tree"
size="16"
/>
<span class="legend-text">{{ item.dataleverancier }}</span>
</div>
</div>
Expand All @@ -60,7 +67,44 @@
>
<v-icon>mdi-chevron-down</v-icon>
</v-btn>
<div class="details d-flex flex-row">
<div
v-if="isTreePanel"
key="tree-panel"
class="details d-flex flex-row"
>
<div class="details__column tree__info">
<h3 class="text-h6">
Boom
{{
bomenLocationsStore.activeTree?.properties?.boomnaam || "..."
}}
</h3>
<v-table>
<tbody>
<tr>
<td>Boomnaam</td>
<td>
{{ boomDataStore.treeName ?? "..." }}
</td>
</tr>
<tr>
<td>Soortgroep</td>
<td>
{{ boomDataStore.groupThatBelongs ?? "..." }}
</td>
</tr>
</tbody>
</v-table>
</div>
<div class="details__column tree__graph">
<TreeHealthChart />
</div>
</div>
<div
v-else
key="location-panel"
class="details d-flex flex-row"
>
<div class="details__column details__table">
<h3 class="text-h6">
Details meetlocatie
Expand Down Expand Up @@ -141,19 +185,26 @@
import { computed, ref, watch } from "vue";
import PeilfilterGraph from "@/components/PeilfilterGraph.vue";
import TimeSeriesChart from "@/components/TimeSeriesChart.vue";
import TreeHealthChart from "@/components/TreeHealthChart.vue";
import { useAppStore } from "@/stores/app";
import { useDepthInfoStore } from "@/stores/depthInfo";
import { useLocationsStore } from "@/stores/locations";
import { useBomenLocationsStore } from "@/stores/bomenLocations";
import { useBoomDataStore } from "@/stores/boomData";
import { useChartTimeseriesStore } from "@/stores/chartTimeseries";
import { usePeilfilterDataStore } from "@/stores/peilfilterData";
import { TREE_COLOR } from "@/lib/constants";

const appStore = useAppStore();
const chartTimeseriesStore = useChartTimeseriesStore();
const depthInfoStore = useDepthInfoStore();
const locationsStore = useLocationsStore();
const bomenLocationsStore = useBomenLocationsStore();
const boomDataStore = useBoomDataStore();
const peilfilterDataStore = usePeilfilterDataStore();

const panelIsCollapsed = computed(() => appStore.panelIsCollapsed);
const isTreePanel = computed(() => !!bomenLocationsStore.activeTree);

const viewMode = computed({
get: () => appStore.viewMode,
Expand All @@ -169,7 +220,6 @@
const legendItems = computed(() => {
const uniqueProviders = new Map();

// locationsStore.locations is now an array, not a FeatureCollection
const locations = locationsStore.locations || [];

locations.forEach((location) => {
Expand All @@ -178,26 +228,47 @@

if (bronId && dataleverancier && !uniqueProviders.has(bronId)) {
uniqueProviders.set(bronId, {
key: `provider-${bronId}`,
bronId,
dataleverancier,
color: getColorForBronId(bronId),
});
}
});

return Array.from(uniqueProviders.values()).sort(
const providers = Array.from(uniqueProviders.values()).sort(
(a, b) => a.bronId - b.bronId
);
if (bomenLocationsStore.bomenLocations?.length > 0) {
providers.push({
key: "trees",
bronId: null,
dataleverancier: "Bomen",
color: TREE_COLOR,
isTree: true,
});
}
return providers;
});

function onLegendItemClick(item) {
if (!item) return;
if (item.isTree) {
appStore.toggleTrees();
return;
}
if (item.bronId == null) return;
appStore.toggleCategory(item.bronId);
}

function getColorForBronId(bronId) {
const colors = {
1: "#008fc5",
2: "#28a745",
3: "#ffc107",
4: "#895129",
};
return colors[bronId] || "#6c757d"; // Gray fallback
return colors[bronId] || "#6c757d";
}

const peilfilterOptions = computed(() => {
Expand Down Expand Up @@ -231,12 +302,17 @@
const hasValidDLabel = computed(() => hasNonEmptyValue(peilfilterDataStore.dlabelFilter));
const hasValidPompId = computed(() => hasNonEmptyValue(peilfilterDataStore.pompidFilter));

function clearPanelDataStores() {
function clearLocationPanelStores() {
chartTimeseriesStore.clearData();
peilfilterDataStore.clearData();
depthInfoStore.clearData();
}

function clearAllPanelStores() {
clearLocationPanelStores();
boomDataStore.clearData();
}

function commaSplit(str) {
if (typeof str !== "string") return [];
return str.split(",").map((s) => s.trim());
Expand All @@ -247,10 +323,15 @@
(newLocation) => {
if (!newLocation) {
selectedPeilfilterId.value = null;
clearPanelDataStores();
if (!bomenLocationsStore.activeTree) {
clearAllPanelStores();
} else {
clearLocationPanelStores();
}
return;
}
clearPanelDataStores();
bomenLocationsStore.setActiveTree(null);
clearAllPanelStores();
const options = peilfilterOptions.value;
selectedPeilfilterId.value =
options.length > 0 ? options[0].value : null;
Expand Down Expand Up @@ -347,12 +428,27 @@
.peilfilter__chart {
flex: 0 0 auto;
width: 250px;
min-width: 0;
min-height: 0;
overflow: hidden;
position: relative;
padding: 0 0;
}

.details__chart {
flex: 1 1 0;
min-width: 0;
min-height: 0;
overflow: hidden;
position: relative;
}

.tree__info {
flex: 0 0 auto;
width: 500px;
}

.tree__graph {
flex: 1 1 0;
overflow: hidden;
position: relative;
Expand Down
Loading
Loading